Android 深色模式(夜间模式)适配指南
Android 10 (API 级别 29) 及更高版本中提供深色主题背景。深色主题背景具有诸多优势:
- 可大幅减少耗电量(具体取决于设备的屏幕技术)。
- 为弱视以及对强光敏感的用户提高可视性。
- 让所有人都可以在光线较暗的环境中更轻松地使用设备。
0x01 DayNight 主题适配深色模式
将应用的主题背景(通常可在 res/values/styles.xml 中找到)设置为继承 DayNight 主题背景。
1 | <style name="AppTheme" parent="Theme.AppCompat.DayNight"> |
用到的资源和颜色需要在 -night
目录中重新配置一份。
在暗黑模式下,系统会优先从 -night
后缀的目录下找到对应的资源配置。
0x02 Force Dark 自动适配深色模式
如果您的应用采用浅色主题背景,则 Force Dark 会分析应用的每个视图,并在相应视图在屏幕上显示之前,自动应用深色主题背景。
Force Dark 应用需要满足以下三个条件
- 使用系统及 AndroidX 提供的浅色主题背景(例如
Theme.Material.Light
) - 在其主题背景中设置
android:forceDarkAllowed="true"
- 手机系统启用深色模式,Android 10 (API 级别 29)以上
如果您的应用使用深色主题(例如 Theme.Material),或者继承自 DayNight 主题背景,则系统不会应用 Force Dark。
在特定 View 上停用 Force Dark,可以通过 android:forceDarkAllowed
布局属性或 setForceDarkAllowed()
。
0x03 动态设置深色模式
如要切换主题背景,请调用 AppCompatDelegate.setDefaultNightMode()。
每个选项直接映射到以下某个 AppCompat.DayNight
模式:
- 浅色 - MODE_NIGHT_NO
- 深色 - MODE_NIGHT_YES
- 由省电模式设置 - MODE_NIGHT_AUTO_BATTERY ( Android 9 或更低版本的设备上)
- 系统默认 - MODE_NIGHT_FOLLOW_SYSTEM ( Android 10 (API 级别 29) 及更高版本上)
注意:从 AppCompat v1.1.0 开始,setDefaultNightMode() 会自动重新创建任何已启动的 Activity。
0x04 切换深色模式不重建 Activity
当应用的主题背景发生更改(无论是通过系统设置还是 AppCompat)时,会触发 uiMode
配置变更。这意味着系统会自动重新创建 Activity。
在某些情况下,您可能希望应用处理配置变更。例如,您可能希望延迟配置变更时间,因为设备正在播放视频。
应用可以声明,每个 Activity 都可以处理 uiMode
配置变更,以自行处理深色主题背景的实现:
1 | <activity |
当某个 Activity 声明它会处理配置变更时,系统会在出现主题背景变更时调用该 Activity 的 onConfigurationChanged()
方法。
0x05 判断是否是深色模式
0x0501 判断当前 APP 是否是深色模式
如要检查当前采用的是哪种主题背景,应用可以运行如下代码:
1 | val currentNightMode = context.resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK |
0x0502 判断当前手机系统是否是深色模式
如果要判断当前手机系统是否是深色模式,可以使用以下代码:
1 | private fun isSystemNightMode(activity: Activity): Boolean { |
如何在 APP 内判断手机是否切换了系统深色模式?
前提是当前 APP 没有使用 android:configChanges="uiMode"
方式。
由于直接通过手机系统快捷设置切换深色模式时,会触发 activity 的 recreate()方法,导致 APP 的 activity 重建,但是在 activity 的 onPause()方法或者 APP 切换到后台时,获取到的深色模式状态已经是切换之后的了。所以,如果要判断 APP 使用过程中,系统是否切换深色模式,目前使用的方式是在进入 activity 时就记录一下当前的系统深色模式状态,然后,onStop 方法去检查系统的设置是否改变,并且把是否切换的值缓存在 APP 全局缓存(注意不能是 Activity 中)里。然后在 App 切换到前台的时候,再去获取缓存中的值,来判断上一次切换到后台时是否是因为系统切换了深色模式。
0x06 老项目深色模式适配指南
- compileSdkVersion 升级到 29 以上
- 使用 Force Dark 自动适配深色模式
- 针对有问题布局建立
-night
资源文件夹,配置对应的 color,drawable 和 layout 等 - APP 中的关键页面使用 DayNight 主题适配,以追求极致的 UI 体验
特别感谢
官网深色主题背景: https://developer.android.google.cn/guide/topics/ui/look-and-feel/darktheme?hl=zh-cn