开发笑话和游戏等一系列app的知识点总结2

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文字轮播~可垂直可水平跑马灯

https://www.jianshu.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滑动冲突解决

https://www.jianshu.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
https://www.jianshu.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标签的宽和高是没有用的,因此不需要设置

https://www.jianshu.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可以加载公众号中的网址。

地址为:https://x5.tencent.com/

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:腾讯的乐高加固

参考网址如下:
https://www.jianshu.com/p/79c16c2101af

85:一个ViewGroup中clipChildren属性的用法,用于将一个子view悬浮于父view之上

https://www.jianshu.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

92:加快gradle的编译速度总结

https://www.jianshu.com/p/200d55b4d40a

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,126评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,254评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,445评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,185评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,178评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,970评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,276评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,927评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,400评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,883评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,997评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,646评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,213评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,204评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,423评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,423评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,722评论 2 345