美文网首页
Android--沉浸式导航栏适配

Android--沉浸式导航栏适配

作者: aruba | 来源:发表于2020-03-19 21:36 被阅读0次
    本文是用于设配SDK4.4到5.0的沉浸式导航栏适配(4.4下面的实现不了沉浸式),上次说到适配沉浸式状态栏时,为DecorView添加一个View可以是实现,导航栏也同样,但是不是所有手机都有导航栏,所以我们先要判断手机有没有导航栏
        public static boolean hasNavigationBar(Context context) {
            WindowManager windowManager = (WindowManager) context.getSystemService(WINDOW_SERVICE);
            //获取物理屏幕的分辨率
            DisplayMetrics realMetrics = new DisplayMetrics();
            windowManager.getDefaultDisplay().getRealMetrics(realMetrics);
    
            //获取屏幕的分辨率(不含导航栏)
            DisplayMetrics contentMetrics = new DisplayMetrics();
            windowManager.getDefaultDisplay().getMetrics(contentMetrics);
    
            //如果竖屏状态下,物理屏幕的高度比内容屏幕的高度高,则含有导航栏,
            //同样,横屏状态下,物理屏幕的宽度比内容屏幕的宽度高,则含有导航栏
            int h = realMetrics.heightPixels - contentMetrics.heightPixels;
            int w = realMetrics.widthPixels - contentMetrics.widthPixels;
            return h > 0 || w > 0;
        }
    
    然后获取NavigationBar的高度
        //使用运行过程中的资源文件
        private static int getNavigationBarHeight(Context context) {
            int statusBarHeight = context.getResources().getIdentifier("navigation_bar_height", "dimen", "android");
            if (statusBarHeight > 0) {
                return statusBarHeight;
            }
    
            //上面方法获取不到的话,使用反射资源获取
            return getNavigationBarHeightByAndroid(context, "com.android.internal.R$dimen", "navigation_bar_height", 48);
        }
    
        private static int getNavigationBarHeightByAndroid(Context context, String className, String fieldName, int defValue) {
            try {
                //获取class
                Class aClass = Class.forName(className);
                //获取实例
                Object o = aClass.newInstance();
                Field field = aClass.getField(fieldName);
                int id = Integer.parseInt(field.get(o).toString());
                return context.getResources().getDimensionPixelOffset(id);
            } catch (Exception e) {
                return defValue;
            }
        }
    
    然后使用之前的套路
        private static final int FAKE_NAVIGATION_BAR_VIEW_ID = R.id.statusbarutil_fake_status_bar_view;
        
        /**
         * 设置导航栏颜色
         *
         * @param activity       需要设置的activity
         * @param color          导航栏颜色值
         * @param statusBarAlpha 导航栏透明度
         */
        public static void setColor(Activity activity, @ColorInt int color, @IntRange(from = 0, to = 255) int statusBarAlpha) {
            if (!hasNavigationBar(activity)) {//没有导航栏直接返回
                return;
            }
    
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
                activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
                activity.getWindow().setNavigationBarColor(calculateNavigationColor(color, statusBarAlpha));
            } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
                activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
                ViewGroup decorView = (ViewGroup) activity.getWindow().getDecorView();
                View fakeNavigationBarView = decorView.findViewById(FAKE_NAVIGATION_BAR_VIEW_ID);
                if (fakeNavigationBarView != null) {
                    if (fakeNavigationBarView.getVisibility() == View.GONE) {
                        fakeNavigationBarView.setVisibility(View.VISIBLE);
                    }
                    fakeNavigationBarView.setBackgroundColor(calculateNavigationColor(color, statusBarAlpha));
                } else {
                    View view = createNavigationBarView(activity, color, statusBarAlpha);
                    FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(view.getLayoutParams());
                    params.gravity = Gravity.BOTTOM;
                    view.setLayoutParams(params);
                    decorView.addView(view);
                }
            }
        }
    
        /**
         * 计算状态栏颜色
         *
         * @param color color值
         * @param alpha alpha值
         * @return 最终的状态栏颜色
         */
        private static int calculateNavigationColor(@ColorInt int color, int alpha) {
            if (alpha == 0) {
                return color;
            }
            float a = 1 - alpha / 255f;
            int red = color >> 16 & 0xff;
            int green = color >> 8 & 0xff;
            int blue = color & 0xff;
            red = (int) (red * a + 0.5);
            green = (int) (green * a + 0.5);
            blue = (int) (blue * a + 0.5);
            return 0xff << 24 | red << 16 | green << 8 | blue;
        }
    
        /**
         * 生成一个和状态栏大小相同的半透明矩形条
         *
         * @param activity 需要设置的activity
         * @param color    状态栏颜色值
         * @param alpha    透明值
         * @return 状态栏矩形条
         */
        private static View createNavigationBarView(Activity activity, @ColorInt int color, int alpha) {
            // 绘制一个和状态栏一样高的矩形
            View statusBarView = new View(activity);
            LinearLayout.LayoutParams params =
                    new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getNavigationBarHeight(activity));
            statusBarView.setLayoutParams(params);
            statusBarView.setBackgroundColor(calculateNavigationColor(color, alpha));
            statusBarView.setId(FAKE_NAVIGATION_BAR_VIEW_ID);
            return statusBarView;
        }
    
    沉浸式NavigationBar.png

    相关文章

      网友评论

          本文标题:Android--沉浸式导航栏适配

          本文链接:https://www.haomeiwen.com/subject/gtxlyhtx.html