Android--沉浸式导航栏适配

2020-07-03 11:23:40 浏览数 (2)

本文是用于设配SDK4.4到5.0的沉浸式导航栏适配(4.4下面的实现不了沉浸式),上次说到适配沉浸式状态栏时,为DecorView添加一个View可以是实现,导航栏也同样,但是不是所有手机都有导航栏,所以我们先要判断手机有没有导航栏
代码语言:javascript复制
    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的高度
代码语言:javascript复制
    //使用运行过程中的资源文件
    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;
        }
    }
然后使用之前的套路
代码语言:javascript复制
    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;
    }

0 人点赞