HarmonyOS 深色模式优雅适配:资源 + 代码双管齐下

前言

深色模式不是简单地"把背景涂黑",它涉及颜色资源的体系化管理、系统色彩模式的监听、以及应用内手动切换的覆盖逻辑。本文基于论坛问题「HarmonyOS 应用如何优雅地做深色模式适配」,给出一套零硬编码、可维护的适配方案,让浅/深两套配色自动切换,同时支持用户手动覆盖。

问题描述

  • 直接写死 0xFFFFFF / 0x000000 等颜色,切换深色模式后界面"一半亮一半暗";
  • 只在某个页面手动判断了深浅,其它页面没适配,风格割裂;
  • 用代码读系统模式后,应用内又想手动切换,结果互相打架、来回闪烁;
  • 图片在深色背景下刺眼,缺乏对应的暗色资源。

细节解析

1. 资源限定词目录(首选,零代码)

HarmonyOS 的资源系统支持 dark 限定词。在 resources/ 下建立 dark/element/color.json,与 base/ 同名字段,框架会根据当前模式自动选择

resources/
├─ base/element/color.json   // 浅色值
└─ dark/element/color.json   // 深色值

UI 里统一用 $r('app.color.background'),无需任何 if/else。

2. 监听系统色彩模式(代码兜底)

EntryAbilityonConfigurationUpdate 能感知系统颜色模式变化,把结果写入 AppStorage,页面用 @StorageProp 读取:

import { ConfigurationConstant } from '@kit.AbilityKit';
onConfigurationUpdate(config: Configuration) {
  const isDark = config.colorMode === ConfigurationConstant.ColorMode.COLOR_MODE_DARK;
  AppStorage.setOrCreate('isDark', isDark);
}

3. 应用内手动切换(覆盖系统)

@StorageLink('isDark') 让页面既能读、也能写。用户手动切后写入 AppStorage,页面立即响应;若想"跟随系统",重新从 config 同步即可。

4. 图片与图标

深色模式优先用 SVG/矢量图;位图则准备 mediamedia/dark 两份,同样走资源限定词自动切换。

示例代码

// 1) resources/base/element/color.json
{ "color": [{ "name": "background", "value": "#FFFFFF" }, { "name": "text", "value": "#000000" }] }
// 2) resources/dark/element/color.json
{ "color": [{ "name": "background", "value": "#1A1A1A" }, { "name": "text", "value": "#E0E0E0" }] }

// 3) EntryAbility.ts
import { ConfigurationConstant } from '@kit.AbilityKit';
export default class EntryAbility extends UIAbility {
  onConfigurationUpdate(config: Configuration) {
    AppStorage.setOrCreate('isDark',
      config.colorMode === ConfigurationConstant.ColorMode.COLOR_MODE_DARK);
  }
}

// 4) 页面
@Entry @Component
struct ThemePage {
  @StorageLink('isDark') isDark: boolean = false;
  build() {
    Column() {
      Text('当前主题:' + (this.isDark ? '深色' : '浅色'))
        .fontColor($r('app.color.text'))
      Button(this.isDark ? '切到浅色' : '切到深色')
        .backgroundColor($r('app.color.background'))
        .onClick(() => { this.isDark = !this.isDark; })
    }
    .width('100%').height('100%')
    .backgroundColor($r('app.color.background'))
  }
}

总结

  • 颜色一律走 $r 资源,用 base + dark 限定词实现零代码自动切换;
  • 系统模式变化用 onConfigurationUpdate 写入 AppStorage
  • 手动切换用 @StorageLink 读写同一份状态,避免与系统模式"打架";
  • 图片用矢量或准备暗色资源,整体才协调。

遵循"资源为主、代码兜底"的原则,深色模式适配就不再是苦力活。

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐