深色模式一开,页面不仅没变暗,反而全白了
系统切到深色模式,页面背景还是白的,状态栏文字却跟着系统变白了,顶部直接看不见;Text 里写死的 Color.Black 在白底上好好的,切过去和深色背景融为一体;更离谱的是,整个应用退到后台再切回来,部分页面的颜色只反转了一半,看着像个半成品。
这真不是系统的深色模式有 bug,而是代码里写死了颜色,系统只认资源。鸿蒙的深色适配核心思路是“差异化声明出来,交给资源目录匹配”,而不是每页去 AppStorage.get('isDark') 然后手写两套色值。
资源限定符的同名映射机制
最小配置只需要两个文件,放在 src/main/resources 下。base/element/color.json 定义浅色值,dark/element/color.json 用相同的资源名定义深色值。
json5
// base/element/color.json
{ "color": [
{ "name": "page_bg", "value": "#FFFFFF" },
{ "name": "page_text", "value": "#182431" }
] }
// dark/element/color.json
{ "color": [
{ "name": "page_bg", "value": "#182431" },
{ "name": "page_text", "value": "#F1F3F5" }
] }
页面里只写 $r('app.color.page_text'),不出现任何布尔判断。系统切色模式时,ResourceManager 自动从 dark 目录取同名资源,组件跟着刷新。
typescript
Column() {
Text('内容').fontColor($r('app.color.page_text'))
}
.width('100%')
.height('100%')
.backgroundColor($r('app.color.page_bg'))
关键语句是 $r()。它指向的是资源名,不是具体色值。资源名不变,值随限定词目录切换,这是整个适配机制的支点。
不要试图用if-else硬切颜色
很多老项目习惯在页面里维护一个 isDark 变量,然后通过判断去切换样式类或者直接改颜色。这种写法不仅维护成本高(每个页面都要加一堆判断),而且极其容易漏。一旦遇到弹窗、Toast、甚至自定义的 Canvas,if-else 的逻辑根本覆盖不全。
如果在开发过程中发现某些颜色在深色模式下依然没变,先全局搜一下代码里有没有硬编码的 Color.White 或者 #FFFFFF。把业务代码里的硬编码颜色全部抽离到 color.json 中,是深色模式适配的第一步,也是最苦但最有效的一步。
Web与Canvas的独立渲染边界
颜色资源解决的是 ArkUI 组件的声明式颜色。Web 组件里加载的网页、Canvas 里自绘的像素,不会因为 dark/element/color.json 就自动反转。这些边界要么单独注入深色样式,要么在深色模式下替换素材。
对于 Web 组件,需要在前端页面里支持 prefers-color-scheme 媒体查询。ArkUI 侧的深色模式切换时,Web 容器的背景色可能已经变了,但网页内部没变,这时候需要通过 runJavaScript 去通知网页切换主题。
typescript
Web({ src: $rawfile('index.html') })
.onPageEnd(() => {
if (isDarkMode()) {
this.controller.runJavaScript('document.body.classList.add("dark")')
}
})
如果你的 Canvas 里有自绘的图表,也要在 Canvas 绘制之前去读取当前的系统颜色模式,判断画笔颜色是否需要反转。不能指望它自动适配。
系统状态栏的跟随策略
沉浸式场景下状态栏文字颜色在深色模式会自动变白。如果你的页面背景做了深浅适配,但某个页面的背景色在深色下仍然偏亮(比如展示了一张浅色的商品大图),状态栏白字就会看不清。
这种情况下,要么让背景色也走资源适配,要么在需要时动态设置状态栏字体颜色。不能只改页面不改状态栏,导致头部信息不可见。
typescript
window.getLastWindow(getContext(this)).then((win) => {
win.setWindowSystemBarProperties({
statusBarContentColor: '#FFFFFF', // 根据实际情况动态设置
})
})
开发警示与后续排查手段
深色适配的工程化答案是把颜色从代码里赶到资源目录里。排查时,先看页面上的硬编码颜色有没有删干净,再看 dark 目录下的颜色值是否符合暗色对比度标准,最后检查 Web 和 Canvas 这些不受系统强制控制的区域。写一个简单的脚本扫描一下全局代码里的 # 开头的颜色值,往往能揪出大量的隐藏地雷。
更多推荐

所有评论(0)