鸿蒙应用深色模式适配:跟随系统与自定义主题切换实战
鸿蒙应用深色模式适配:跟随系统与自定义主题切换实战
深色模式早已不是“换个背景色”那么简单。用户在夜间打开应用时刺眼的白屏、跟随系统切换时闪烁的界面、以及深色下看不清的文字,都会直接影响留存。本文讲清楚鸿蒙应用深色模式的适配思路:先跟随系统,再给用户手动选择的权利。
一、深色模式的两种来源:系统与应用内设置
鸿蒙应用的颜色模式一般来自两个地方:
- 系统设置:用户在系统设置里选择了深色或浅色,应用默认跟随。
- 应用内设置:应用提供“跟随系统 / 浅色 / 深色”三档选择,用户的选择优先于系统。
一个合理的优先级是:用户在应用内明确选过,就用用户的选择;没选过,就跟随系统。这个规则写进代码之前先定下来,后面所有判断都按它走,避免出现“改了设置不生效”这类问题。
二、颜色不要写死:用资源文件管理两套配色
最常见的适配错误,是把颜色值直接写在组件里:
// 不推荐:颜色写死,换主题时无从下手
Text('你好').fontColor('#1A1A1A')
正确的做法是把颜色定义在资源文件里,给同一语义准备浅色和深色两套值:
// element/color.json
{
"color": [
{ "name": "text_primary", "value": "#1A1A1A" },
{ "name": "bg_page", "value": "#FFFFFF" }
]
}
// element/dark/color.json
{
"color": [
{ "name": "text_primary", "value": "#F2F2F2" },
{ "name": "bg_page", "value": "#121212" }
]
}
组件里只引用语义化的资源名:
Text('你好').fontColor($r('app.color.text_primary'))
系统切换深浅色时,框架会自动取对应资源文件里的值,页面不需要逐个改颜色。记住一条原则:组件里出现具体色值,就是以后要还的技术债。
三、监听切换:让页面平滑过渡
颜色模式变化时,应用可以通过系统能力感知到当前模式。关键点有三个:
- 启动时读一次当前模式,决定首屏用哪套配色,避免先白后黑的闪烁。
- 运行时监听模式变化,系统切换后页面自动刷新,不用重启应用。
- 切换时加过渡:颜色突变会让用户觉得“闪了一下”。给背景和文字加一个短时间的颜色过渡动画,体验会顺滑很多。
图片资源也要注意:浅色下好看的浅色 Logo,在深色背景上可能几乎看不见。给关键图片准备深色版本,或者用深色下对比度足够的图标样式。
四、深色不是简单反色:几个容易踩的坑
把浅色界面直接反色,得到的多半是一个难用的深色界面:
- 纯黑背景慎用:大面积纯黑配纯白文字对比过强,长时间阅读容易疲劳。深灰(如 #121212)通常比纯黑更舒服。
- 文字层级要重新调:浅色下用灰色区分次要文字,在深色下可能直接“隐身”。深色模式的次要文字需要更高的亮度。
- 阴影会失效:浅色界面靠阴影区分层级,深色下阴影几乎看不见。改用边框线或微弱的亮度差来区分卡片和背景。
- 别忘了 WebView 与富文本:内嵌网页和富文本内容有自己的颜色体系,需要单独处理,否则会出现深色页面里嵌一块白色网页的割裂感。
五、应用内三档切换的实现思路
给用户一个设置页,提供三档选择:
- 跟随系统:默认项,应用随系统变化自动切换。
- 浅色:强制浅色,不受系统影响。
- 深色:强制深色,不受系统影响。
实现上用一个持久化存储保存用户选择,应用启动时读取:有明确选择就按选择来,没有就跟随系统。设置页切换后立即生效并保存,下次打开应用保持上次的选择。
测试时别只测一种情况:系统浅色 + 应用强制深色、系统深色 + 应用强制浅色、系统切换时应用处于前台、应用在后台时系统切换后再回到前台,这几种组合都过一遍。
六、上线前的检查清单
- 所有颜色都走资源文件,代码里没有写死的色值。
- 文字在深色下的对比度足够,主次层级分明。
- 图片、图标、启动页在深色下都正常显示。
- 系统切换、应用内切换、前后台切换都不会闪烁或错乱。
- WebView、弹窗、Toast 等边缘场景也覆盖了深色样式。
结语
深色模式适配的核心不是“多做一套皮肤”,而是把颜色从代码里抽出来,交给资源系统管理。语义化的颜色资源搭好之后,跟随系统和手动切换都只是水到渠成的事。先从颜色资源化开始,再补切换逻辑和细节打磨,深色模式就能稳稳地落地。
- 点赞
- 收藏
- 关注作者
评论(0)