16:标准的伸缩式toolbar布局
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<android.support.design.widget.AppBarLayout
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="192dp"
>
<android.support.design.widget.CollapsingToolbarLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
app:contentScrim="?attr/colorPrimary"
app:layout_scrollFlags="scroll|exitUntilCollapsed"
app:toolbarId="@+id/toolbar"
>
<ImageView
android:id="@+id/imageview12"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_collapseMode="parallax"
app:layout_collapseParallaxMultiplier="0.5" />
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:navigationIcon="@drawable/ic_keyboard_backspace_white_36dp"
app:layout_collapseMode="pin"
/>
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<android.support.v4.widget.NestedScrollView
android:id="@+id/scroll"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_behavior="android.support.design.widget.AppBarLayout$ScrollingViewBehavior">
<LinearLayout
android:id="@+id/linea"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/textView4"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:layout_marginLeft="7dp"
android:layout_marginRight="7dp"
android:text="TextView"
android:textSize="20dp" />
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
</android.support.design.widget.CoordinatorLayout>
17:仿探探滑动效果,修改将喜欢和不喜欢按钮放入卡片内即可。
https://github.com/shallcheek/shallcheek_tantan
18:如果要给Toolbar设置title和title的颜色的话,这时Toolbar还是CollapsingToolbarLayout的子view,那么直接给Toolbar设置title和title的颜色是没有效果的,这时可以给CollapsingToolbarLayout设置title,至于title的颜色在xml文件中的CollapsingToolbarLayout视图中是不能直接设置的,但是代码中可以进行设置,代码如下:
collapsingToolbarLayout.setCollapsedTitleTextColor(getResources().getColor(R.color.white));
collapsingToolbarLayout.setExpandedTitleColor(getResources().getColor(R.color.white));
19:一个一样的图片放在drawable文件夹下,和放在mitmap文件夹下,然后通过代码展示出来的效果是不一样的,mitmap下更小了,图标放在mitmap文件夹下,其他图片及xml文件放在drawable文件夹下。
20:android studio 无法下载插件的解决方法
https://blog.csdn.net/qq_37405874/article/details/80341606?utm_source=blogxgwz5
21:Android获取TextView行数getLineCount()返回0的解决方法:
https://blog.csdn.net/qq_18524107/article/details/52795648
22:DialogFragment的使用(比较靠外层的view的宽度必须是match_parent,不然dialog就变形了)
示例代码如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:orientation="vertical"
android:paddingBottom="40dp"
android:paddingTop="40dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="50.4dp"
android:layout_centerHorizontal="true"
android:layout_marginBottom="4.4dp"
android:layout_marginLeft="50dp"
android:layout_marginRight="50dp">
<LinearLayout
android:id="@+id/xiantiao"
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_alignParentBottom="true"
android:background="@color/white"
android:orientation="vertical" />
<TextView
android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_above="@id/xiantiao"
android:gravity="center_vertical"
android:text="账号"
android:textColor="@color/black"
android:textSize="18sp" />
<EditText
android:id="@+id/own_login_input_user"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="@id/xiantiao"
android:layout_toRightOf="@id/text"
android:background="@null"
android:digits="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
android:gravity="center"
android:hint="请输入用户名"
android:inputType="number"
android:maxLength="10"
android:paddingBottom="0.6dp"
android:singleLine="true"
android:textColor="@color/black"
android:textColorHint="@color/gray"
android:textSize="18sp" />
<ImageView
android:id="@+id/own_login_delete_user"
android:layout_width="22.2dp"
android:layout_height="22.2dp"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginRight="13.3dp"
android:src="@drawable/input_delete"
android:visibility="gone" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_alignParentBottom="true"
android:background="@color/gray" />
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="50.4dp"
android:layout_centerHorizontal="true"
android:layout_marginBottom="7.4dp"
android:layout_marginLeft="50dp"
android:layout_marginRight="50dp">
<LinearLayout
android:id="@+id/xiantiao1"
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_alignParentBottom="true"
android:background="@color/white"
android:orientation="vertical" />
<TextView
android:id="@+id/text1"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_above="@id/xiantiao1"
android:gravity="center_vertical"
android:text="密码"
android:textColor="@color/black"
android:textSize="18sp" />
<EditText
android:id="@+id/own_login_input_password"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_toRightOf="@id/text1"
android:background="@null"
android:digits="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
android:gravity="center"
android:hint="请输入密码"
android:inputType="number"
android:maxLength="10"
android:paddingBottom="0.6dp"
android:password="true"
android:singleLine="true"
android:textColor="@color/black"
android:textColorHint="@color/gray"
android:textSize="18sp" />
<ImageView
android:id="@+id/own_login_delete_password"
android:layout_width="22.2dp"
android:layout_height="22.2dp"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginRight="13.3dp"
android:src="@drawable/input_delete"
android:visibility="gone" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_alignParentBottom="true"
android:background="@color/gray" />
</RelativeLayout>
<TextView
android:id="@+id/own_login_image"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_centerVertical="true"
android:layout_marginLeft="50dp"
android:layout_marginRight="50dp"
android:layout_marginTop="30dp"
android:background="@drawable/buttonbeijing"
android:gravity="center"
android:paddingBottom="0.6dp"
android:paddingRight="0.6dp"
android:text="登录"
android:textColor="@color/white"
android:textSize="17sp" />
<TextView
android:layout_width="match_parent"//这个TextView的宽度如果是wrap_content的话,那么就变形了,match_parent不会变形
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:text="账号注册?"
android:gravity="center_horizontal"
android:textColor="@color/colorPrimary" />
</LinearLayout>
</LinearLayout>
参考网址:
https://www.cnblogs.com/mercuryli/archive/2016/04/09/5372496.html
23:Activity 与 DialogFragment 之间的数据传递
https://blog.csdn.net/zhang5690800/article/details/70182494
24:Android文字轮播~可垂直可水平跑马灯
//www.greatytc.com/p/2b6c9a82d973
25:水平滑动的recyclerview,可以自动归位
https://github.com/CarlLee/SnappingSwipingRecyclerView
26:一个可以在代码中直接设置margin的方法(已记录)
public class ViewMarginUtils {
public static ViewGroup.LayoutParams setViewMargin(View view, boolean isDp, int left, int right, int top, int bottom) {
if (view == null) {
return null;
}
int leftPx = left;
int rightPx = right;
int topPx = top;
int bottomPx = bottom;
ViewGroup.LayoutParams params = view.getLayoutParams();
ViewGroup.MarginLayoutParams marginParams = null;
//获取view的margin设置参数
if (params instanceof ViewGroup.MarginLayoutParams) {
marginParams = (ViewGroup.MarginLayoutParams) params;
} else {
//不存在时创建一个新的参数
marginParams = new ViewGroup.MarginLayoutParams(params);
}
//根据DP与PX转换计算值
if (isDp) {
leftPx = ConvertUtils.dp2px(view.getContext(), left);
rightPx = ConvertUtils.dp2px(view.getContext(), right);
topPx = ConvertUtils.dp2px(view.getContext(), top);
bottomPx = ConvertUtils.dp2px(view.getContext(), bottom);
}
//设置margin
marginParams.setMargins(leftPx, topPx, rightPx, bottomPx);
view.setLayoutParams(marginParams);
return marginParams;
}
}
参考网址
https://blog.csdn.net/u011374875/article/details/52150471
27:抽屉布局记录一下,可以直接在DrawerLayout内使用要进行侧滑的布局,然后设置其属性android:layout_gravity="start" 即可(用该属性来在DrawerLayout中标识该布局是否是侧滑布局),如果要用NavigationView的话,想要自定义menu的样子的话,当布局到了底部的话,会出现无法显示的情况,因此直接用自己的布局就行。
28:通过OnScrollListener来监听RecyclerView当前位置的item的索引(item的大小为全屏的情况下),通过layoutmanager来获取的
https://blog.csdn.net/qq_21265915/article/details/61930096
29:获取recyclerView中某个item中的view,通过layoutmanager来获取的
https://blog.csdn.net/d06110902002/article/details/68495853
30:下面的这个tab库具有viewpager懒加载功能,以前就用过这个库
compile 'com.flyco.tablayout:FlycoTabLayout_Lib:2.1.2@aar'
31:可以在父布局中使用如下代码来阻止子view初始化时就获取焦点
android:focusable="true"
android:focusableInTouchMode="true"
32:debug调试:
32.1:Step Over(F8)一行一行的执行代码,相对粗略的调试方法,推荐这种调试方法
32.2:Step Into(F7)一行一行的执行代码,非常详细的调试,系统的执行代码也可以看到
32.3:Run to Cursor(Alt+F9)直接执行到第一个打断点的代码处,再按下之后执行第二个打断点的代码处,依次类推。
执行一行代码后,可以在调试面板的variables处查看执行到这行代码时,各个变量中的值的具体情况。
32.4:可以在变量第一次使用的地方打上断点,然后开始调试之后通过variables面板点击变量然后通过右键的setValue来给变量设置调试过程中的值。
33:以泛型的方式判断一个引用是否为空
try {
getT(lin);
} catch (Exception e) {
Log.e("yichang", "onCreate: " + e.getMessage());
}
private <T> T getT(T t) throws Exception {
if (t == null)
throw new Exception("t为空");
return t;
}
34:点击一个按钮让edittext获得焦点的方法:requestFocus(),打开软键盘用KeybordUtil工具类
35:接口回调的应用:
public class MyImageView extends ImageView {
private Paint paint;
private Bitmap bitmap;
private Context mContext;
private DeleteInterface deleteInterface;
public int index = -1;
public MyImageView(Context context) {
super(context);
init(context);
}
public MyImageView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public MyImageView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}
public void setDeleteInterface(DeleteInterface deleteInterface) {
this.deleteInterface = deleteInterface;
}
@TargetApi(Build.VERSION_CODES.KITKAT)
private void init(final Context context) {
mContext = context;
paint = new Paint();
paint.setColor(Color.RED);
paint.setStyle(Paint.Style.FILL);
bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.bacha2);
setOnTouchListener(
new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
Log.e("chudian", "onTouch: " + event.getX() + "," + event.getY());
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
if (event.getX() > getWidth() - bitmap.getWidth() && event.getY() < bitmap.getHeight()) {
if (deleteInterface != null) {
deleteInterface.setDelete(true, index);
}
}
}
return true;
}
}
);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawBitmap(bitmap, getWidth() - bitmap.getWidth(), 0, paint);
}
public interface DeleteInterface {
void setDelete(boolean b, int index);
}
}
...
if (mImageCaptureUri != null) {
try {
bitmap = getBitmapFormUri(this, mImageCaptureUri);
MyImageView imageView = new MyImageView(this);
imageView.setLayoutParams(new ViewGroup.LayoutParams(ConvertUtils.dp2px(this, 100), ConvertUtils.dp2px(this, 100)));
imageView.setImageBitmap(bitmap);
imageView.setDeleteInterface(new MyImageView.DeleteInterface() {
@Override
public void setDelete(boolean b, int index) {
if (b) {
for (int i = 0; i < tupianlinear.getChildCount(); i++) {
if (tupianlinear.getChildAt(i) instanceof MyImageView && ((MyImageView) tupianlinear.getChildAt(i)).index == index) {
tupianlinear.removeView(tupianlinear.getChildAt(i));
}
}
}
}
});
tupianlinear.addView(imageView, 0);
imageView.index = count;
count++;
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
...
36:接口回调的理解,接口回调就是要获取一个数据,但是这个数据是在之后才能获取到,那我们就可以在那个数据所在的类中新建接口创建接口回调,当满足一定条件后通知其他位置该数据已经获取到了。
37:特别注意onBackPressed这个方法中的super.onBackPressed(),super.onBackPressed()所在代码中的位置不同会造成很大的差别。
@Override
public void onBackPressed() {
if (lin.getVisibility()==View.VISIBLE) {
lin.setVisibility(View.GONE);
}else {
super.onBackPressed();
}
}
38:listview有个方法:smoothScrollToPositionFromTop,滚动到某个位置,并且可以设置该位置距离屏幕顶部的距离,代码如下所示:
listView.smoothScrollToPositionFromTop(arg2,0);//滚动到arg0所在item的位置并且arg0所在的item距离顶部的距离为0
39:split的用法:
String s="我是生死时速时候说是四";
Log.e("CeShiActivity", "s: "+s.split("\\[").length );
Log.e("CeShiActivity", "s: "+s.split("\\[")[0]);
//Log.e("CeShiActivity", "s: "+s.split("\\[")[1]);//报ArrayIndexOutOfBoundsException异常
Log.e("CeShiActivity", "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
String s1="sss[";
Log.e("CeShiActivity", "s1: "+s1.split("\\[").length );
Log.e("CeShiActivity", "s1: "+s1.split("\\[")[0]);
//Log.e("CeShiActivity", "s1: "+s1.split("\\[")[1]);////报ArrayIndexOutOfBoundsException异常
Log.e("CeShiActivity", "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
String s2="[sss";
Log.e("CeShiActivity", "s2: "+s2.split("\\[").length );
Log.e("CeShiActivity", "s2: "+s2.split("\\[")[0]);
Log.e("CeShiActivity", "s2: "+s2.split("\\[")[1]);
Log.e("CeShiActivity", "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
String s3="我是生死时速时候说是四[sss";
Log.e("CeShiActivity", "s3: "+s3.split("\\[").length );
Log.e("CeShiActivity", "s3: "+s3.split("\\[")[0]);
Log.e("CeShiActivity", "s3: "+s3.split("\\[")[1]);
Log.e("CeShiActivity", "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
/*12-12 14:00:08.755 14427-14427/duanzi.b.dzkj.kezhan E/CeShiActivity: s: 1
12-12 14:00:08.755 14427-14427/duanzi.b.dzkj.kezhan E/CeShiActivity: s: 我是生死时速时候说是四
12-12 14:00:08.755 14427-14427/duanzi.b.dzkj.kezhan E/CeShiActivity: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
12-12 14:00:08.755 14427-14427/duanzi.b.dzkj.kezhan E/CeShiActivity: s1: 1
12-12 14:00:08.755 14427-14427/duanzi.b.dzkj.kezhan E/CeShiActivity: s1: sss
12-12 14:00:08.755 14427-14427/duanzi.b.dzkj.kezhan E/CeShiActivity: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
12-12 14:00:08.755 14427-14427/duanzi.b.dzkj.kezhan E/CeShiActivity: s2: 2
12-12 14:00:08.755 14427-14427/duanzi.b.dzkj.kezhan E/CeShiActivity: s2:
12-12 14:00:08.755 14427-14427/duanzi.b.dzkj.kezhan E/CeShiActivity: s2: sss
12-12 14:00:08.755 14427-14427/duanzi.b.dzkj.kezhan E/CeShiActivity: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
12-12 14:00:08.755 14427-14427/duanzi.b.dzkj.kezhan E/CeShiActivity: s3: 2
12-12 14:00:08.755 14427-14427/duanzi.b.dzkj.kezhan E/CeShiActivity: s3: 我是生死时速时候说是四
12-12 14:00:08.755 14427-14427/duanzi.b.dzkj.kezhan E/CeShiActivity: s3: sss
12-12 14:00:08.755 14427-14427/duanzi.b.dzkj.kezhan E/CeShiActivity: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
40:ImageView的setImageResource方法和setBackgroundResource方法是有区别的:当用CircleImageView设置圆形头像框时,用setImageResource设置出来的就是圆形的,而setBackgroundResource却不是。
41:listview具有视图复用的功能,即使不用setTag,也有视图复用功能,当你修改了一个item中的数据后,只要该item还在屏幕上,那么修改后的内容就会在,当你把修改后的item滑出屏幕后,这个item就被回收了,被其他item复用了,当再次滑动到修改后的item时,发现内容被还原了,这是因为每个item重新出现在屏幕时适配器中的getView方法都会被调用一次,重新填充数据,我们可以通过修改传过来的list中的数据达到视图不会被还原的效果,在适配器以外,当listview调用notifyDataSetChanged时,是让适配器中的getCount()方法重新执行一次,获得最新的item个数,如果是增加item的话就让新增加的item重新执行一次getView方法。
42: 通过获取imageview的drawable,然后转换为bytes类型,然后就可以和其他图片转换成的bytes进行比较,如果两个图片一样的话,那么转换后的bytes是一样的,如果不一样,说明不是同一个图片。代码如下所示:
if(Arrays.equals(ConvertUtils.bitmap2Bytes(ConvertUtils.drawable2Bitmap(finalHolder_one_image.dianzan.getDrawable()), Bitmap.CompressFormat.PNG),ConvertUtils.bitmap2Bytes(BitmapFactory.decodeResource(context.getResources(), R.drawable.weidianzan), Bitmap.CompressFormat.PNG))) {...}
43:当调试app时,在一个公共方法打上断点后,很多地方都会用到,但你只想在某一处调试,那么这时就可以attach debugger to android process。不用从项目一开始就调试,可以打开app后,然后在想调试的地方附着调试就行。
44: glide加载图片后具有缓冲的功能,尤其是加载网络图片后(那时候是修改了头像更新不过来),当网络图片修改了,但还是加载出了以前的图片,这是可以使用以下代码进行缓冲的清理:
RequestOptions r=new RequestOptions().skipMemoryCache(false).diskCacheStrategy(DiskCacheStrategy.NONE);
45:当json数据中出现"contentPictures": []时,判空不是if (list.get(position).getContentpictures()!=null)而是if (!list.get(position).getContentpictures().equals("[]"))
46:适配器中的viewholder不要写成成员变量,不然会出现各种奇怪的现象,示例代码如下:
if (holder_one_image.dianzan != null) {
if (list.get(position).getIsDianZan() == 1)
holder_one_image.dianzan.setImageResource(R.drawable.yidianzan);
final ViewHolder_one_image finalHolder_one_image = holder_one_image;
holder_one_image.dianzan.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
DownJson downJson = new DownJson(30, 3001, articleid, 0);
downJson.FreedomLoadTask(new DownJson.FreedomCallback() {
@Override
public void jsonLoaded(String[] json, String tag) {
if (tag.equals("ready")) {
JSONObject jsonObject = null;
try {
jsonObject = new JSONObject(json[0]);
int i = jsonObject.getInt("result");
if (i == 1) {
if (Arrays.equals(ConvertUtils.bitmap2Bytes(ConvertUtils.drawable2Bitmap(finalHolder_one_image.dianzan.getDrawable()), Bitmap.CompressFormat.PNG), ConvertUtils.bitmap2Bytes(BitmapFactory.decodeResource(context.getResources(), R.drawable.weidianzan), Bitmap.CompressFormat.PNG))) {
finalHolder_one_image.dianzancount.setText(Integer.parseInt(finalHolder_one_image.dianzancount.getText().toString()) + 1 + "");
list.get(position).setComment_like(Integer.parseInt(finalHolder_one_image.dianzancount.getText().toString()));
list.get(position).setIsDianZan(1);
Toast.makeText(context, "点赞成功", Toast.LENGTH_SHORT).show();
finalHolder_one_image.dianzan.setImageResource(R.drawable.yidianzan);
}
} else
Toast.makeText(context, "点赞失败", Toast.LENGTH_SHORT).show();
} catch (JSONException e) {
e.printStackTrace();
}
}
}
});
downJson.execute(Utils.url);
}
});
}
47:在'android' #551 包中找不到属性'appComponentFactory'的资源标识符的解决方式如下:(原因是sdk用的是android-p(api28)的缘故,而你的ide没有androidapi28的sdk)
https://github.com/android/android-ktx/issues/551
48:ScrollView嵌套RecyclerView滑动冲突解决
//www.greatytc.com/p/5dfc90656665
49:对NestedScrollView的滑动监听
nestedScrollView.setOnScrollChangeListener(new NestedScrollView.OnScrollChangeListener() {
@Override
public void onScrollChange(NestedScrollView v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) {
if (scrollY - oldScrollY > 0) {
//将Y属性变为底部栏高度 (相当于隐藏了)
((Main_Activity) getActivity()).showOrHideBottomNavigation(false);
} else if (scrollY - oldScrollY < 0) {
((Main_Activity) getActivity()).showOrHideBottomNavigation(true);
}
}
});
在Main_Activity.java文件中
...
public void showOrHideBottomNavigation(boolean show) {
if (show) {
bottomNavigation.animate().translationY(0);
} else {
bottomNavigation.animate().translationY(ConvertUtils.dp2px(this, 56));
}
}
...
参考网址:
https://blog.csdn.net/qq_35058792/article/details/79499292
50:可以在recyclerview的适配器中重写getItemViewType方法来给item的布局添加标识,继而给item添加不同布局。
51:在androidmanifest.xml文件中加入如下代码可以防止activity因为屏幕旋转而销毁:
android:configChanges="keyboardHidden|orientation|screenSize"
参考网址:https://www.cnblogs.com/dmtyoung/p/6673910.html
52:Android中实现带有头部的GridView(HeaderGridView)
https://blog.csdn.net/ch1451082329/article/details/46801497
53:xml布局文件中的视图id最好不要出现重复的,不然当布局文件多的时候,会出现报错现象
54:用androidstudio打jar的方法
参考网址:https://www.cnblogs.com/yxx123/p/5280347.html
55:ProguardGui进行jar包代码混淆(更加详细的内容看虎哥发的混淆文件)
-injars ruyicai.jar //需要混淆的jar包
-outjars ruyicai-out.jar //混淆完毕输出的jar包
//引用依赖的jar包
-libraryjars 'C:\Program Files\Java\jdk1.6.0_43\jre\lib\rt.jar'
… ...
-libraryjars libs\weibo-1.2.jar
-optimizationpasses 5
-dontusemixedcaseclassnames
-dontskipnonpubliclibraryclasses
-dontpreverify
-verbose
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
//在混淆的过程中,建议保留Activity,Application四大组件,其它的类可根据实际情况设置是否混淆
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Application
-keep public class * extends android.app.Service
… …
//保留某个类不被混淆
-keep public class com.ruyicai.activity.common.PullRefreshListView{*;}
//不混淆第三方的jar包
-keep class com.alipay.android.app.**{*;}
… ...
-keep class cn.jpush.android.**{*;}
//后面的规则使用默认的,这里不在描述
… ….
参考网址:https://www.cnblogs.com/suncoolcat/p/3347890.html
56:Timer类,示例代码如下:
new Timer().schedule(new TimerTask() {
@Override
public void run() {
}
},1000);//延迟1秒后执行run方法中的内容,并且run方法中的内容是工作在子线程中的。
57:方法中的参数带有...表示该参数有很多个,可以接收任意多个参数,可以在方法内部数组来指向。
private void showBannerMulti(Activity a, Object... objects) {
Object[] bannerObject = objects;
...
}
58:枚举的定义:
public enum ADPLATFORM {
NONE, GDT, BAIDU;
}
枚举值的引用:
private ADPLATFORM nativeType = ADPLATFORM.NONE;
枚举值的比较:
if (bannerType == ADPLATFORM.NONE) {...}
59:获取Androidmanifest文件中meta-data标签中某个name的值,示例代码如下:
ApplicationInfo ai;
try {
ai = context.getPackageManager()
.getApplicationInfo(context.getPackageName(),
PackageManager.GET_META_DATA);
if (null != ai)
metaData = ai.metaData;
} catch (NameNotFoundException e) {
e.printStackTrace();
}
if (null != metaData) {
UMENG_CHANNEL = metaData.getString("UMENG_CHANNEL");
}
60:一个activity中,所有能看到的view的context都可以强制装换为该activity,然后就可以调用该activity中的公共方法了。
61:如果子view处理了单击事件后,父view将不会再处理单击事件
62:自定义view的xml属性(在attrs.xml文件中书写):
<declare-styleable name="AbsListView">
<attr name="listSelector" format="color|reference"/>
<attr name="transcriptMode">
<enum name="disabled" value="0"/>
<enum name="normal" value="1"/>
<enum name="alwaysScroll" value="2"/>
</attr>
</declare-styleable>
63:一个非常好用的图片选择器,示例代码如下:
public class MainActivity extends AppCompatActivity {
private LinearLayout xianshi;
private Button photo;
private List<LocalMedia> selectList = new ArrayList<>();
private RecyclerView recyclerView;
private GridImageAdapter adapter;
private int maxSelectNum = 20;
private ExecutorService executorService;
private Button xiangxi;
private ArrayList<MyEntity> arrayList;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
xianshi = findViewById(R.id.xianshi);
photo = findViewById(R.id.photo);
xiangxi = findViewById(R.id.xiangxi);
recyclerView = findViewById(R.id.recycler);
executorService = Executors.newSingleThreadExecutor();
photo.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
/* Intent intent = new Intent();
intent.setAction(Intent.ACTION_GET_CONTENT);
intent.setType("image*//*");
startActivityForResult(intent, 100);*/
/* PictureSelector.create(MainActivity.this).openGallery(PictureMimeType.ofAll()).selectionMode(PictureConfig.MULTIPLE)
.previewImage(true).selectionMedia(selectList).forResult(100);*/
if (selectList.size() == 0) {
Toast.makeText(MainActivity.this, "请先选择要扫描的图片", Toast.LENGTH_SHORT).show();
} else {
xianshi.removeAllViews();
saoMiaoImage();
}
}
});
FullyGridLayoutManager manager = new FullyGridLayoutManager(this, 4, GridLayoutManager.VERTICAL, false);
recyclerView.setLayoutManager(manager);
adapter = new GridImageAdapter(this, onAddPicClickListener);
adapter.setList(selectList);
adapter.setSelectMax(maxSelectNum);
recyclerView.setAdapter(adapter);
adapter.setOnItemClickListener(new GridImageAdapter.OnItemClickListener() {
@Override
public void onItemClick(int position, View v) {
LocalMedia media = selectList.get(position);
String pictureType = media.getPictureType();
int mediaType = PictureMimeType.pictureToVideo(pictureType);
switch (mediaType) {
case 1:
// 预览图片
PictureSelector.create(MainActivity.this).themeStyle(R.style.picture_default_style).openExternalPreview(position, selectList);
break;
}
}
});
xiangxi.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (selectList.size() == 0) {
Toast.makeText(MainActivity.this, "请先选择要扫描的图片", Toast.LENGTH_SHORT).show();
} else {
Intent intent = new Intent(MainActivity.this, XiangXiActivity.class);
intent.putParcelableArrayListExtra("datalist", arrayList);
startActivity(intent);
}
}
});
}
/* public void updateAdapter() {
for (int i = 0; i < selectList.size(); i++) {
recyclerView.getChildAt(i).findViewById(R.id.fail).setVisibility(View.GONE);
}
}*/
private void saoMiaoImage() {
arrayList = new ArrayList<>();
TextView t = new TextView(MainActivity.this);
t.setText("被PS编辑过的图片如下所示:");
t.setTextSize(20);
t.setTextColor(getResources().getColor(R.color.colorPrimary));
xianshi.addView(t);
LinearLayout l = new LinearLayout(MainActivity.this);
l.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 1));
l.setBackgroundColor(getResources().getColor(R.color.blue));
xianshi.addView(l);
for (int i = 0; i < selectList.size(); i++) {
final int finalI = i;
final int finalI1 = i;
executorService.execute(new Runnable() {
StringBuffer stringBuffer;
@Override
public void run() {
Metadata metadata = null;
try {
metadata = ImageMetadataReader.readMetadata(new File(selectList.get(finalI).getPath()));
} catch (ImageProcessingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
stringBuffer = new StringBuffer();
for (Directory directory : metadata.getDirectories()) {
for (Tag tag : directory.getTags()) {
stringBuffer.append("名字为:" + directory.getName() + ",标签名为:" + tag.getTagName() + ",描述为:" + tag.getDescription() + "\n\n");
}
if (directory.hasErrors()) {
for (String error : directory.getErrors()) {
stringBuffer.append("错误为:" + error + "\n");
}
}
}
arrayList.add(new MyEntity(stringBuffer.toString(), finalI1));
runOnUiThread(new Runnable() {
@Override
public void run() {
//xianshi.setText(stringBuffer);
if (stringBuffer.toString().contains("Photoshop")) {
TextView t = new TextView(MainActivity.this);
t.setText("第" + (finalI1 + 1) + "张图片被PS编辑过");
t.setTextColor(getResources().getColor(R.color.colorPrimary));
xianshi.addView(t);
//selectList.get(finalI1).setChecked(true);
// recyclerView.getChildAt(finalI1).findViewById(R.id.fail).setVisibility(View.VISIBLE);
Log.e("ConvertUtils", finalI1 + "");
//Toast.makeText(MainActivity.this, "经过Photoshop处理", Toast.LENGTH_SHORT).show();
}
}
});
}
});
}
Log.e("ConvertUtils", "---------------------------------");
}
private GridImageAdapter.onAddPicClickListener onAddPicClickListener = new GridImageAdapter.onAddPicClickListener() {
@Override
public void onAddPicClick() {
PictureSelector.create(MainActivity.this).openGallery(PictureMimeType.ofAll()).selectionMode(PictureConfig.MULTIPLE).maxSelectNum(maxSelectNum)
.previewImage(true).selectionMedia(selectList).forResult(100);
}
};
@Override
protected void onActivityResult(int requestCode, int resultCode, final Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 100) {
selectList = PictureSelector.obtainMultipleResult(data);
adapter.setList(selectList);
adapter.notifyDataSetChanged();
for (int i = 0; i < selectList.size(); i++) {
Log.e("ConvertUtils", selectList.get(i).isChecked() + "");
}
}
}
}
https://github.com/LuckSiege/PictureSelector
64:一个可以检测图片信息的库:(注意不要使用最新的,最新的不能扫描jpg格式的图片,要用metadata-extractor-2.8.1.jar和xmpcore-5.1.2.jar)
https://github.com/drewnoakes/metadata-extractor/releases
https://blog.csdn.net/itsonglin/article/details/46405313
65:如何监听CollapsingToolbarLayout的展开与折叠
http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2016/0619/4362.html
66:有时候项目会出现一些奇怪的现象,明明代码是正确的,但是执行结果却不对,这时候就需要clean一下项目了,然后就正常了。
67:android textview 文本在代码中设置粗体效果
https://blog.csdn.net/chuyouyinghe/article/details/78774339
68:Android studio 中gradle版本不一样导致运行问题Error:Unable to find method 'com.android.build.gradle.tasks.factory
https://blog.csdn.net/u013441613/article/details/80582893
69:解决androidstudio安装apk速度慢的原因:
https://blog.csdn.net/l_215851356/article/details/53858378
//www.greatytc.com/p/68140ac6a5fe
70:确保代码只执行一次的方法,用变量控制
private boolean isAcessSecondClick;
private void ClickSecond() {
if (isAcessSecondClick) {
return;
}
isAcessSecondClick = true;
...
}
71:Android RadioGroup和RadioButton详解
http://www.cnblogs.com/Im-Victor/p/6238437.html
72:Android之TableLayout(表格布局),示例代码如下:
<TableLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TableRow
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="?attr/actionBarSize"
android:layout_weight="1"
android:gravity="center"
android:text="TextView" />
<LinearLayout
android:layout_width="1dp"
android:layout_height="match_parent"
android:background="@color/huise" />
<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="?attr/actionBarSize"
android:layout_weight="1"
android:gravity="center"
android:text="TextView" />
<LinearLayout
android:layout_width="1dp"
android:layout_height="match_parent"
android:background="@color/huise" />
<TextView
android:id="@+id/textView3"
android:layout_width="wrap_content"
android:layout_height="?attr/actionBarSize"
android:layout_weight="1"
android:gravity="center"
android:text="TextView" />
</TableRow>
</TableLayout>
注意:设置TableRow标签的宽和高是没有用的,因此不需要设置
//www.greatytc.com/p/77599d96d499
73:FFmpeg库的使用
https://github.com/microshow/RxFFmpeg
74:这个播放器很厉害,视频不是流,是文件也能播放
https://github.com/tcking/GiraffePlayer2
75:浏览器中的开发者工具可以很快的锁定某个视图所用的css,然后就可以到源码中更改了
76:安卓加载webView只显示部分网页的方法,只能是在onPageFinished方法中才能隐藏
根据class来隐藏
public void onPageFinished(WebView paramWebView, String paramString) {
Log.e("onPageFinished", "onPageFinished: " + paramString);
String fun="javascript:function getClass(parent,sClass) { var aEle=parent.getElementsByTagName('div'); var aResult=[]; var i=0; for(i<0;i<aEle.length;i++) { if(aEle[i].className==sClass) { aResult.push(aEle[i]); } }; return aResult; } ";
webView.loadUrl(fun);
String fun2="javascript:function hideOther() {getClass(document,'div_gonggao')[0].style.display='none';getClass(document,'div_gonggao')[0].style.top=35;}";
webView.loadUrl(fun2);
webView.loadUrl("javascript:hideOther();");
super.onPageFinished(paramWebView, paramString);
}
根据id来隐藏
public void onPageFinished(WebView paramWebView, String paramString) {
Log.e("onPageFinished", "onPageFinished: " + paramString);
String fun="javascript:function getId(parent,sId) { var aEle=parent.getElementsByTagName('div'); var aResult=[]; var i=0; for(i<0;i<aEle.length;i++) { if(aEle[i].id==sId) { aResult.push(aEle[i]); } }; return aResult; } ";
webView.loadUrl(fun);
String fun2="javascript:function hideOther() {getId(document,'div_gonggao')[0].style.display='none';getId(document,'div_gonggao')[0].style.top=35;}";
webView.loadUrl(fun2);
webView.loadUrl("javascript:hideOther();");
super.onPageFinished(paramWebView, paramString);
}
参考网址:
https://blog.csdn.net/benhuo931115/article/details/52180363
另外如果是超链接的话,还有如下方式修改网页的内容
public WebResourceResponse shouldInterceptRequest(WebView webView, String s) {
Log.e("shouldInterceptRequest", "shouldInterceptRequest: " + s);
if (s.contains("image/icon11.png"))
return new WebResourceResponse("image/png", "UTF-8", Bitmap2InputStream(drawable2Bitmap(getDrawable(R.mipmap.ic_launcher)), 100));
return super.shouldInterceptRequest(webView, s);
}
public InputStream Bitmap2InputStream(Bitmap bm, int quality) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bm.compress(Bitmap.CompressFormat.PNG, quality, baos);
InputStream is = new ByteArrayInputStream(baos.toByteArray());
return is;
}
public Bitmap drawable2Bitmap(Drawable drawable) {
Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(),
drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565);
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
drawable.draw(canvas);
return bitmap;
}
参考网址:
https://blog.csdn.net/qq_25474979/article/details/51178591
另外注意了:如果一个js代码出现错误的话,那个这个js代码块中后续代码将不会执行,比如getClass(document,'share-nav')得到的节点数组为null的话,那么就会报出错误,然后剩下的两个getId函数将不会被执行;其次就是可以通过console.log来查看具体的变量的信息,很好用。代码如下所示:
String fun = "javascript:function getId(parent,sId) { var aEle=parent.getElementsByTagName('div'); var aResult=[]; var i=0; for(i<0;i<aEle.length;i++) { if(aEle[i].id==sId) { aResult.push(aEle[i]); } }; return aResult; } ";
String fun1 = "javascript:function getClass(parent,sClass) { var aEle=parent.getElementsByTagName('nav'); var aResult=[];console.log('一次了'+aEle.length); var i=0; for(i<0;i<aEle.length;i++) { if(aEle[i].className==sClass) { aResult.push(aEle[i]); console.log('一次了');} }; return aResult; } ";
webView.loadUrl(fun);
webView.loadUrl(fun1);
String fun2 = "javascript:function hideOther() {getClass(document,'share-nav')[0].style.display='none';getId(document,'div_gonggao')[0].style.display='none';getId(document,'div_cate1')[0].style.display='none';}";
再来一个相对完整一点的代码:如果不知道html标签的具体属性的话,可以下载hbuilder来查看
String fun = "javascript:function getNavClass(parent,sClass) { var aEle=parent.getElementsByTagName('nav'); var aResult=[]; var i=0; for(i<0;i<aEle.length;i++) { if(aEle[i].className==sClass) { aResult.push(aEle[i]);} }; return aResult; } ";
String fun1 = "javascript:function getImg(parent,sSrc) { var aEle=parent.getElementsByTagName('img'); var aResult=[];var i=0; for(i<0;i<aEle.length;i++) { if(aEle[i].src==sSrc) { aResult.push(aEle[i]);} }; return aResult; } ";
String fun2 = "javascript:function getDivClass(parent,sClass) { var aEle=parent.getElementsByTagName('div'); var aResult=[]; var i=0; for(i<0;i<aEle.length;i++) { if(aEle[i].className==sClass) { aResult.push(aEle[i]); } }; return aResult; } ";
String fun3 = "javascript:function getAllImg(parent,sSrc) { console.log('哈哈');var aEle=parent.getElementsByTagName('img'); var i=0; for(i<0;i<aEle.length;i++) {console.log('哈哈'+aEle[i].src); if(aEle[i].src==sSrc) { aEle[i].src=''} };}";
webView.loadUrl(fun);
webView.loadUrl(fun1);
webView.loadUrl(fun2);
webView.loadUrl(fun3);
String fun4 = "javascript:function hideOther() {if(getNavClass(document,'share-nav').length!=0){getNavClass(document,'share-nav')[0].style.display='none';}" +
"if(getImg(document,'https://yy6080.co/template/org/images/logo.png').length!=0){getImg(document,'https://yy6080.co/template/org/images/logo.png')[0].style.display='none';}" +
"getAllImg(document,'https://yy6080.co/template/org/images/load.gif');" +
"if(getDivClass(document,'footer clearfix').length!=0){getDivClass(document,'footer clearfix')[0].style.display='none';}}";
webView.loadUrl(fun4);
webView.loadUrl("javascript:hideOther();");
77:腾讯浏览服务:腾讯自己的webview可以加载公众号中的网址。
78:微信公众号中的网址是不能使用电脑中的浏览器打开的,如果要查看网页源码的话,需要在手机版的谷歌浏览器中输入对应的网址,然后在网址前面加上view-source:既可以查看网页的源代码。
79:android.support.design.widget包下面有个BottomSheetDialog,这个是底部弹出框,系统自带的,代码如下所示:
BottomSheetDialog bottomSheetDialog=new BottomSheetDialog(this);
bottomSheetDialog.setContentView(R.layout.fragment_dialog_tixing);
ListView listView=bottomSheetDialog.findViewById(R.id.fragment_dialog_list);
initAdatper(listView);
bottomSheetDialog.show();
80:Android中ExpandableListView的使用,该类在android.widget包下
参考网址:
https://blog.csdn.net/sysukehan/article/details/51960473
https://github.com/sysukehan/AndroidTests/blob/master/ExpandableListViewTest/src/main/java/com/study/android/kehan/androidtests/ExpandableListViewTestActivity.java
81:当把一个图片保存到手机后,这时用微信的扫一扫是找不到那个图片的,需要等待一段时间才能显示出来,这是我们就需要更新系统的相册,这样就不用等待时间了,代码如下:
String path = savePhoto(drawable2Bitmap(imageView.getDrawable()), "/storage/emulated/0/热门电影大全", "热门game之家二维码");
try {
MediaStore.Images.Media.insertImage(MainActivity.this.getContentResolver(),
path, "热门game之家二维码.jpg", null);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
Uri uri = Uri.fromFile(new File(path));
intent.setData(uri);
MainActivity.this.sendBroadcast(intent);
参考网址:
https://www.cnblogs.com/Sharley/p/7942142.html
82:AlertDialog的用法,老话题了,再记录一下
AlertDialog.Builder dialog = new AlertDialog.Builder(MainActivity.this)
.setTitle("APP更新通知")
.setMessage("请及时更新APP,来享受最新的APP带来的乐趣")
//.setView(R.layout.updateapp)
.setNeutralButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
}
}).setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
new Thread(new Runnable() {
@Override
public void run() {
updateApp();
}
}).start();
}
});
dialog.show();
参考文章:
https://blog.csdn.net/f552126367/article/details/80497583
83:关于系统自带的Android下载器DownloadManager的使用
代码如下所示:用DownloadManager的话,可以先将apk以json格式进行存储,然后设置下载好后设置类型为apk即可。
private void updateApp() {
DownloadManager downloadManager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
DownloadManager.Request req = new DownloadManager.Request(Uri.parse("http://**/1.json"));
//设置流量下进行更新
req.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_MOBILE);
//下载中和下载完后都显示通知栏
req.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
//使用系统默认的下载路径 此处为应用内 /android/data/packages ,所以兼容7.0
// req.setDestinationInExternalFilesDir(this, Environment.DIRECTORY_DOWNLOADS, "/storage/emulated/0/热门电影大全.apk");
//通知栏标题
req.setTitle("热门电影大全");
//通知栏描述信息
req.setDescription("正在下载...");
//设置类型为.apk
req.setMimeType("application/vnd.android.package-archive");
long l=downloadManager.enqueue(req);
Log.d("DownloadManager",l+"");
}
注册接收apk下载完成的广播
<receiver
android:name=".DownloadReceiver"
android:enabled="true"
android:exported="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
<intent-filter>//只有设置了intent-filter,到时候发出的下载完成的intent才能被广播接收者接收到,如果没有intent-filter的话,默认是不接受任何intent的
<action android:name="android.intent.action.DOWNLOAD_COMPLETE" />
<action android:name="android.intent.action.DOWNLOAD_NOTIFICATION_CLICKED" />
</intent-filter>
</receiver>
在res文件夹下创建xml文件夹,然后在创建file_paths文件,内容如下://因为Android7.0以上获取文件的保密性更强了
<?xml version="1.0" encoding="utf-8"?>
<resources>
<paths>
<files-path path ="" name = "download"/>
</paths>
</resources>
在DownloadReceiver文件中
public class DownloadReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(DownloadManager.ACTION_DOWNLOAD_COMPLETE)) {
long id = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);
installApk(context, id);
} else if (intent.getAction().equals(DownloadManager.ACTION_NOTIFICATION_CLICKED)) {
// DownloadManager manager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
//获取所有下载任务Ids组
//long[] ids = intent.getLongArrayExtra(DownloadManager.EXTRA_NOTIFICATION_CLICK_DOWNLOAD_IDS);
////点击通知栏取消所有下载
//manager.remove(ids);
//Toast.makeText(context, "下载任务已取消", Toast.LENGTH_SHORT).show();
//处理 如果还未完成下载,用户点击Notification ,跳转到下载中心
Intent viewDownloadIntent = new Intent(DownloadManager.ACTION_VIEW_DOWNLOADS);
viewDownloadIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(viewDownloadIntent);
}
}
private void installApk(Context context, long downloadApkId) {
Log.d("DownloadManager",downloadApkId+"");
DownloadManager dManager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
Uri apkUri = dManager.getUriForDownloadedFile(downloadApkId);
if(Build.VERSION.SDK_INT>=24) {//判读版本是否在7.0以上
Intent install = new Intent(Intent.ACTION_VIEW);
install.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
install.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);//添加这一句表示对目标应用临时授权该Uri所代表的文件
install.setDataAndType(apkUri, "application/vnd.android.package-archive");
context.startActivity(install);
}else {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(apkUri, "application/vnd.android.package-archive");
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
}
}
}
知识点总结:
1:用DownloadManager的话,可以先将apk以json格式进行存储,然后设置下载好后设置类型为apk即可。
2:只有设置了intent-filter,到时候发出的下载完成的intent才能被广播接收者接收到,如果没有intent-filter的话,默认广播是不接受任何intent的,只有intent的action满足广播的action才会接受到
3:Android7.0以上获取文件的路径有所不同
参考网址:
https://blog.csdn.net/huangbin123/article/details/78742012
https://blog.csdn.net/qq_31588719/article/details/77224049
84:腾讯的乐高加固
参考网址如下:
//www.greatytc.com/p/79c16c2101af
85:一个ViewGroup中clipChildren属性的用法,用于将一个子view悬浮于父view之上
//www.greatytc.com/p/4a89d80284de
86:android:layout_gravity="bottom"意思是子view的底部与父view的底部对齐
87:泛型的<T>需要放在类名后面才不报错,比如public class BmobUtils<T extends BmobObject> {...}
泛型的?是这样用的,在方法的返回值或者是参数中用的
public List<? extends BmobObject> getEntityList(String tableName) {...}
public void getEntityList(List<? extends BmobObject> c) {...}
泛型主要是用来进行限制的,<>中必须是具体的类的名字,不能是类名的引用,比如Class c;<c>这是错误的
88:可以通过fragment中的getView方法来得到fragment中的布局
89:复制文本到剪切板
//获取剪贴板管理器:
ClipboardManager cm = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
// 创建普通字符型ClipData
ClipData mClipData = ClipData.newPlainText("Label", "XQ113143");
// 将ClipData内容放到系统剪贴板里。
cm.setPrimaryClip(mClipData);
90:修改alertdialog的大小位置及获取alertdialog中视图的id(已记录)
View view = getLayoutInflater().inflate(R.layout.dialog, null);
final AlertDialog alertDialog = new AlertDialog.Builder(this)
.setView(view)
.create();
alertDialog.getWindow().setBackgroundDrawable(getResources().getDrawable(R.drawable.yuanxing1));
view.findViewById(R.id.open).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
}
});
view.findViewById(R.id.later).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
alertDialog.dismiss();
}
});
alertDialog.show();
//注意修改alertdialog的大小位置必须在alertdialog调用了show()方法后之后才能生效
Window window = alertDialog.getWindow();
WindowManager.LayoutParams layoutParams = window.getAttributes();
layoutParams.width = dp2px(this, 280);
//layoutParams.height= WindowManager.LayoutParams.WRAP_CONTENT;
//layoutParams.x=90;
//layoutParams.y=90;
window.setAttributes(layoutParams);
同理也可以在activity加载完毕后通过获取activity中的window来修改activity的位置,代码如下所示:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
init();
Window window=getWindow();
WindowManager.LayoutParams layoutParams=window.getAttributes();
layoutParams.x=500;
layoutParams.y=500;
window.setAttributes(layoutParams);
}
总结:dialog和activity都是展示在window上面的,因此可以通过修改window的位置和大小属性来间接的修改dialog和activity的位置和显示大小。
91:跳转到微信
https://www.jb51.net/article/130510.htm