Android--沉浸式导航栏适配

2023-10-27

转自:Android--沉浸式导航栏适配_Aruba233的博客-CSDN博客

本文是用于设配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
————————————————
版权声明:本文为CSDN博主「Aruba233」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_24000367/article/details/120796222

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android--沉浸式导航栏适配 的相关文章

随机推荐

  • 什么是抽象类

    抽象概念 当我们在做子类共性功能抽取时 有些方法在父类中并没有具体的体现 这个时候就需要抽象类了 在Java中 一个没有方法体的方法应该定义为抽象方法 而类中如果有抽象方法 该类必须定义为抽象类 抽象方法 没有方法体的方法 抽象类 包含抽象
  • Unity层级

    层级 层级是Unity中场景物体的一种属性 摄像机可以指明渲染层级以渲染场景中的部分物体 灯光可以指明照射层级以照亮部分物体 可以指定照亮某些层级的物体以显示阴影 层级还能用于设置物理碰撞关系 层级顺序 Unity中的渲染顺序自上而下大致分
  • 关于 Math.random()生成指定范围内的随机数的公式推导

    优质资源分享 学习路线指引 点击解锁 知识定位 人群定位 Python实战微信订餐小程序 进阶级 本课程是python flask 微信小程序的完美结合 从项目搭建到腾讯云部署上线 打造一个全栈订餐系统 Python量化交易实战 入门级 手
  • 用VS2015编译QGIS3.16.9源码

    TOC VS2015编译QGIS3 16 9源码 编译QGIS源码 由于编译QGIS时涉及依赖的开源库很多 过程比较麻烦 特在此记录编译的完整过程 以方便同道中人参考 同时也方便本人以后编译忘记步骤时回头看看 接下来就开干 一 VS2015
  • c语言输出txt文件不对齐,用fprintf函数打印同样的内容,样子不同。百度无解,望大佬帮忙...

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 这是我的全部代码 功能是实现随机生成20个20以内的不重复的加减法 如果大佬们对我的代码思路和代码风格有什么建议 也希望能不吝赐教 include include include define
  • CSDN高校俱乐部2012年秋季巡讲安排及讲师介绍

    CSDN高校俱乐部2012年秋季巡讲行程在各位讲师 主席和指导教师的给力支持下已初步出炉 部分学校仍需要确认时间安排 大多数学校已确定巡讲时间 时间表列在下方 讲师介绍在最后 阵容强大值得期待 学校名单及安排 场序 地区 城市 分组 学校
  • SpringMVC视图解析器

    SpringMVC视图解析器 SpringMVC中的视图解析器的主要作用就是将逻辑视图转换成用户可以看到的物理视图 当用户对SpringMVC应用程序发起请求时 这些请求都会被SpringMVC的DispatcherServlet处理 通过
  • Xcode 调试之 Hello World

    编译 编译JKD 可以查看 Mac 编译 OpenJDK 8 调试 截图来自 https segmentfault com a 1190000005082098 调试 Hello World 编写好源文件 public class Hell
  • Linux命令行另类使用技巧

    0x00 基础简述 0x01 补全实践 bash completion zsh autosuggestions 文件名补全 特殊补全 命令行参数补齐 可编程补全 0x02 历史命令 设置历史记录 查看历史命令 搜索历史命令 前后移动历史命令
  • CSS层叠性(重要)

    CSS层叠性 重要 指多种CSS样式的叠加 是浏览器处理冲突的一个能力 如果一个属性通过两个相同选择器设置到同一个元素上 那么这个时候一个属性就会将另一个属性层叠掉 原则 1 样式冲突 遵循的原则是就近原则 即CSS的书写位置 2 样式不冲
  • 【2022年MathorCup大数据竞赛】B题:北京移动用户体验影响因素研究(一)

    目录 一 题目背景 二 初赛问题 三 数据集的分享 一 题目背景 移动通信技术飞速发展 给人们带来了极大便利 人们也越来越离不开移动通信技术带来的各种便捷 随着网络不断的建设 网络覆盖越来越完善 各个移动运营商 越来越重视客户的网络使用体验
  • 判断文件的几种方法及其优劣对比

    目录 一 懒人的try语句 二 传统的os模块 三 时尚的pathlib模块 四 几种方法优劣对比 我们知道当 件不存在的时候 open 法的写模式与追加模式都会新建 件 但是对 件进 判 我们之前学过 要 with语句来处理 件读写 但w
  • shell脚本生成两个数据日期之间的所有日期

    在linux下有时候会需要得到两个日期之间的所有日期 作为变量进行处理 例如两个日期之间的所有日期都分别生成一个用日期命名的文件夹 以下shell脚本循环输出两个指定日期之间的所有日期 包括两个输入日期 bin bash 以YYYYMMDD
  • 排列数【第十届】【决赛】【B组】

    在一个排列中 一个折点是指排列中的一个元素 它同时小于两边的元素 或者同时大于两边的元素 对于一个 1 n 的排列 如果可以将这个排列中包含 t个折点 则它称为一个 t 1 单调序列 例如 排列 1 4 2 3 是一个 3 单调序列 其中
  • GTK+的优点与QT的优点

    想看看图形界面系统的优缺点 转载了网友整理的 GTK 的优点与QT的优点整理 在嵌入式 Linux 下有很多图形界面系统 GUI 包括 Qt Embedded FLTK Microwindows 和 GTK 等 作为一个开发者 到底使用什么
  • YOLOv8+ByteTrack多目标跟踪(行人车辆计数与越界识别)

    课程链接 https edu csdn net course detail 38901 ByteTrack是发表于2022年的ECCV国际会议的先进的多目标跟踪算法 YOLOv8代码中已集成了ByteTrack 本课程使用YOLOv8和By
  • arcgis已试图对空几何执行该操作_ArcGIS中坐标转换和投影变换

    当不同来源 不同坐标系统的空间数据要在一起使用 相互参照时 就要进行坐标转换 如果涉及不同的地图投影 就要进行投影变换 动态投影 所谓动态投影 是指改变ArcMap中的数据框架 DataFrame 的空间参考或者对后加入ArcMap中的数据
  • liunx常用命令

    在liunx中可能有几百个命令 最常用的就10多个 liunx中最常用的命令 ls 功能 使用说明 案例 pwd 功能 使用说明 案例 cd 功能 使用说明 案例 mkdir 功能 使用说明 案例 touch 功能 使用说明 案例 rm 功
  • 动力节点 SpringBoot教程 p15 Whitelabel Error Page

    一步一步跟着王妈妈敲的 还是报错 后来发现是目录的问题 initiizer初始化出来application和comtroller不在一个包下面 把他挪到controller包下面就ok了 或者把他挪到和controller目录一个层次也可以
  • Android--沉浸式导航栏适配

    转自 Android 沉浸式导航栏适配 Aruba233的博客 CSDN博客 本文是用于设配SDK4 4到5 0的沉浸式导航栏适配 4 4下面的实现不了沉浸式 上次说到适配沉浸式状态栏时 为DecorView添加一个View可以是实现 导航