前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Android--沉浸式导航栏适配

Android--沉浸式导航栏适配

作者头像
aruba
发布2020-07-03 11:23:40
1.6K0
发布2020-07-03 11:23:40
举报
文章被收录于专栏:android技术android技术
本文是用于设配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;
    }
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 本文是用于设配SDK4.4到5.0的沉浸式导航栏适配(4.4下面的实现不了沉浸式),上次说到适配沉浸式状态栏时,为DecorView添加一个View可以是实现,导航栏也同样,但是不是所有手机都有导航栏,所以我们先要判断手机有没有导航栏
  • 然后获取NavigationBar的高度
  • 然后使用之前的套路
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档