Android Q暗色模式适配踩坑—状态栏
暗色模式已经不是什么新鲜玩意了,大家最近看到关于暗色模式最多的内容可能就是iOS版本微信未适配暗色模式面临被AppStore下架的风险。然后今天早上一醒来,发现Android的微信也黑了(因为我手机一直用的暗色模式),然后最近也遇到了一个暗色模式适配的一个坑,就拿出来讲一讲。
适配暗色模式
在开始之前还是提一下,暗色模式的一个适配方式。这个谷歌官方讲的很清楚,方式有两种:
- 定义两套主题(正常模式和黑暗模式)
这种方式较为复杂,需要在style下定义正常模式和暗色模式两套app_theme,且必须继承自Theme.AppCompat.DayNight.DarkActionBar,然后提取出需要适配暗色模式的属性,最后在BaseActivity的onCreate方法中,根据当前模式设置不同的主题即可。判断系统当前是否暗色模式:
public boolean isDarkMode() {int mode = getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK;return mode == Configuration.UI_MODE_NIGHT_YES;
}
- 设置forceDarkAllowed属性
这种方式简单粗暴,只需要app_theme中声明
<item name="android:forceDarkAllowed">true</item>
应用会在系统切换暗色时,自动适配,这个前提就是不要使用硬编码颜色值。同样需要准备两套资源,暗色模式需要的资源文件,放在以values-night命名的资源目录下,在不同模式下,会自动读取对应目录下的资源。
forceDrakAllowed不仅可以用在App主题级别,也可以直接使用在View上。如果仅需某个View适配暗色模式,直接在view属性声明即可。同理,如果某个View在暗色模式下,不需要适配,通过设置forceDrakAllowed为false即可,或者通过view.setForceDarkAllowed(false)。
遇到的bug
暗色模式下,状态栏没有反色,导致看不清。
这个很好定位,肯定是StatusBar状态写死了,去代码里面看看
private void setStatusBarColor() {Window window = getWindow();window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);window.setStatusBarColor(Color.TRANSPARENT);window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
}
可以看到,之前应该是因为某种业务需要,所以将状态栏设置了LIGHT_STATUS_BAR这个flag。
方案一:
我们知道,如果不认为去设置SystemUI的Visibility,系统会自动根据当前主题颜色来适配状态栏是否进行反色,那么我们如果去掉这个这个人为设置的flag, 是否就可以解决这个问题。
private void setStatusBarColor() {Window window = getWindow();window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);window.setStatusBarColor(Color.TRANSPARENT);//去掉LIGHT_STATUS_BAR这个flag//window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
}
结果如下:
暗色模式虽然状态栏反色了,但是正常模式下,又看不到了。也就是说,暗色模式下的状态栏,需要自己适配。并且,Activity的内容与状态栏出现了重叠。
方案二:
既然无法自动反色,那就适配咯,原本逻辑咱们不改动,加个判断在暗色模式时,咱们设置一个DRAK_STATUS_BAR属性是不是就可以了。开玩笑哈,View属性里面并没有这个flag,需要通过位运算来处理
private void setStatusBarColor() {Window window = getWindow();window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);window.setStatusBarColor(Color.TRANSPARENT);if (isDarkMode()) {int uiOption = window.getDecorView().getSystemUiVisibility();//没有DARK_STATUS_BAR属性,通过位运算将LIGHT_STATUS_BAR属性去除window.getDecorView().setSystemUiVisibility(uiOption & ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);} else {window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);}
}
结果如下:
正常模式和暗色模式,状态栏都已经正常反色,但是暗色模式下,Activity内容依然与状态栏重叠。
方案三:
通过对比不难发现,只有暗色模式重叠,无非就是因为我们保留了之前所设置的FLAG,这里要注意,这里的FLAG是通过set方法来设置的,也就是说,后面的只会覆盖前面的,而不像我们平时所使用的addFlags,这个是叠加的。
再来回顾一下,没有修改前的代码:
private void setStatusBarColor() {Window window = getWindow();window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);//第一次set了两个属性window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);window.setStatusBarColor(Color.TRANSPARENT);//这里又一次set,也就是前面的e两个属性根本没有使用window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
}
而我们出现重叠的原因,就是因为保留了之前的属性,其中SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN就是导致重叠的真凶,作用是在不隐藏StatusBar的情况下,将view所在window的显示范围扩展到StatusBar下面。之所以正常模式下,不会出现重叠,是因为二次设置LIGHT_STATUS_BAR会覆盖前面的属性。
很明显,我们的内容并不需要延伸至状态栏下,所以前面的代码就是无用的,删除即可。
private void setStatusBarColor() {Window window = getWindow();window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);//window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE// | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);window.setStatusBarColor(Color.TRANSPARENT);int uiOption = window.getDecorView().getSystemUiVisibility();if (isDarkMode()) {//没有DARK_STATUS_BAR属性,通过位运算将LIGHT_STATUS_BAR属性去除window.getDecorView().setSystemUiVisibility(uiOption & ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);} else {//这里是要注意的地方,如果需要补充新的FLAG,记得要带上之前的然后进行或运算window.getDecorView().setSystemUiVisibility(uiOption | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);}
}
最后的真凶,并不是暗色模式导致了重叠,而是原代码作者留下的坑。主要还是对于SystemUI Flag的一些属性不熟导致。OK,修改完效果如下。
对于SystemUI的一些FLAG作用不清楚的同学,可以参考下面这个文章:
https://www.jianshu.com/p/e6656707f56c
更多完整面试专题和进阶知识分享,尽在“Android扫地僧”
Android Q暗色模式适配踩坑—状态栏相关推荐
- Android 10深色主题适配踩坑记录
1. 问题简述 Android 10 推出了深色主题,便于用户根据白天和夜晚自由切换合适的主题.在适配的过程中,要特别注意,切换主题会导致当前activity被重建,也就是会重新走一遍Activity ...
- 转:android.support升级到androidx踩坑记录
原文链接:android.support升级到androidx踩坑记录 - 简书 年前想着Google老大之前提醒过将项目升级到androidx,所以年前一通操作猛如虎把Android Studio唰 ...
- android gradle权威指南pdf_干货 | 携程 Android 10适配踩坑指南
作者简介 曙光,携程资深软件工程师,负责市场营销相关研发及管理工作.2019 年 9 月 3 日,Google 发布了 Android 10 正式版.Android 10 聚焦移动创新.安全隐私和数字 ...
- React-Native android在windows下的踩坑记
坑很多,跳之前做好准备.没有VPN的同学请浏览完本文后慎行. 你需要先安装最新版本的node.js(我最后使用的是v4.1.2),前往官网下载>> 注:我win7已经安装过Visual S ...
- Android Studio打包~安卓打包踩坑及总结
一..Android Studio,打开自己的项目中的android,点击确定 二.点击OK后自动执行右上角大象标志.同步项目与Gradle文件. 三.点击最下面一排的build,可以实时看到进度和报 ...
- Android SDK 开发——发布使用踩坑之路
前言 在 Android 开发过程中,有些功能是通用的,或者是多个业务方都需要使用的. 为了统一功能逻辑及避免重复开发,因此将该功能开发成一个 SDK 是相当有必要的. 背景 刚好最近自己遇到了类似需 ...
- STM32L051 低功耗模式和踩坑随笔(自用)
这几天用到了STM32L051的低功耗.之前也接触过低功耗,各种模式有些迷糊,正好整理一下. 手册上说有5个模式,功耗依次递减. 低功耗运行模式:调压器处于低功耗模式,时钟频率受限. 进入方式: 配置 ...
- android q 桌面模式,Android Q带来全新桌面模式
IT之家3月14日消息 谷歌在美国当地时间3月13日(北京时间14日凌晨)正式推送了Android Q的首个Beta版本,"亲儿子"Pixel系列全系手机可以尝鲜体验这最新的系统. ...
- Android Q之提前适配攻略(一)(图标适配)
转自:https://blog.csdn.net/qq_37199105/article/details/89632104 前言: Android Q在2019年的3月份发布了beta1版本,这算是近 ...
最新文章
- linux——管理系统设备之磁盘的加密、加密磁盘的挂载及磁盘阵列、配额
- Unity3D基础28:Invoke计时函数与碰撞销毁
- Bootstrap 使用教程 与jQuery的Ajax方法
- Windows10下编译Nginx源码
- app测试和web测试的区别
- python和c语言的哪个难,r语言和c语言哪个难 r语言和python的区别-与非网
- PDF旋转保存居然还能如此高效的办法
- 中国标准走进国际视野,首个零信任国际标准的诞生往事
- SpringCloudAlibaba——Nacos实现原理详解
- 我的挣扎 与 TBtools 的开发
- 解决使用ssh工具远程连接到服务器上因为网络波动而需要重连的问题
- 简单的RTSP播放器
- 克隆虚拟机 - hyperv
- 武汉新时标文化传媒有限公司新型网红经济爆发式增长
- 【Unity3D】相机
- 安居客上市,难挑58大梁?
- JAVA设计模式什么鬼(观察者)——作者:凸凹里歐
- PostgreSQL 锁等待诊断详解
- ldd3学习之七:中断处理
- 如何评价OA系统的易用性
热门文章
- minui点击分页控件后滚动条置顶
- kasp技术原理_SNP检测Massarray法怎么样?中高通量大样本适用吗?
- Hadoop Java对应版本号
- Android 自定义相机黑屏
- 柏西机器人_《勿忘我》孔木猴 ^第15章^ 最新更新:2020-08-03 17:37:51 晋江文学城_手机版...
- 在EntityFramework中使用 nock的方法。
- 友盟统计使用及添加测试设备(设备ID及Mac地址识别)
- cobble批量装机原理与部署
- Android实现仿QQ登录可编辑下拉菜单
- Cannot create symlink/symbolic to `xxx': Operation not supported