HarmonyOS 鸿蒙Next的深色模式该如何适配?

HarmonyOS 鸿蒙Next的深色模式该如何适配? HarmonyOS的深色模式该如何适配?有知指导吗?

10 回复

更多关于HarmonyOS 鸿蒙Next的深色模式该如何适配?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


【问题背景】:HarmonyOS的深色模式该如何适配?

【解决思路】

  1. 应用跟随系统的深浅色模式:应用颜色 / 资源随系统模式自动切换;
  2. 应用主动设置深浅色模式:应用固定某一模式,不随系统变化。

一、应用跟随系统深浅色模式

需从颜色、图片、组件、监听等维度实现适配,核心是通过 “资源配置” 或 “系统资源调用” 实现自动切换。

1. 颜色适配(两种实现方式)

实现方式 核心逻辑 代码示例核心片段
自定义资源 resources目录下新增dark限定词目录,创建color.json,与基础目录同名配色设不同色值 基础目录:"app_title_color": "#000000";dark 目录:"app_title_color": "#FFFFFF"
系统资源(推荐) 直接调用系统预置资源(分层参数),同一资源 ID 随模式自动变值,保证视觉风格统一 Text('文本').fontColor($r('sys.color.ohos_id_color_text_primary'))

2. 图片资源适配

  • 普通图片:在dark/media目录放与基础目录同名的深色图片,通过$r('app.media.xxx')加载,系统自动切换;
  • SVG 图标:无需两套图片,通过fillColor绑定系统资源实现颜色切换,示例:
    Image($r('app.media.pic_svg')).width(50).fillColor($r('sys.color.ohos_id_color_text_primary'))

3. 特殊组件适配

  • Web 组件:需单独配置前端页面深色模式,参考 “Web 组件深色模式” 文档;
  • 自定义节点(BuilderNode/ComponentContent):需手动传递系统环境变化事件,通过updateConfiguration()触发全量更新,需在FrameCallbackonFrame()中调用更新逻辑。

4. 监听系统模式切换事件

无论是否跟随系统,该监听均生效,用于自定义资源初始化逻辑,分 4 步:

  1. AbilityStage.onCreate()中,将当前颜色模式存入AppStorage
    AppStorage.setOrCreate('currentColorMode', this.context.config.colorMode)
  2. AbilityStage.onConfigurationUpdate()中,刷新AppStorage的模式值;
  3. 在 Page 中用@StorageProp + @Watch监听模式变化:
    @StorageProp('currentColorMode') @Watch('onColorModeChange') currentMode: number = ...
  4. aboutToAppear()(初始化)和onColorModeChange()(切换时)中执行适配逻辑。

5. 局部深浅色适配

通过WithTheme组件设置局部模式(跟随系统 / 浅色 / 深色),作用范围内的组件样式将按指定模式读取资源,详情参考 “设置应用页面局部深浅色” 文档。

三、应用主动设置深浅色模式

应用默认跟随系统,若需固定模式,通过setColorMode接口实现:

  1. 固定为浅色模式(未适配深色时推荐,避免显示异常):
onCreate(): void {
  this.context.getApplicationContext().setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_LIGHT);
}
  1. 重置为跟随系统(全系统组件开发时,需显式设置以保证切换):
    this.context.getApplicationContext().setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET)

四、系统判定应用深浅色模式的规则

  1. 优先级 1:应用主动调用setColorMode,则以接口设置为准;
  2. 优先级 2:未主动设置时:
    • 若工程有dark目录及深色资源,系统组件自动切深色;
    • 若无dark目录资源,系统组件保持浅色。

五、使用建议与注意事项

1. 推荐方法

  • 跟随系统时,用AbilityStageAbility的监听回调,绑定状态变量执行业务逻辑,确保模式切换时逻辑生效。

2. 不推荐方法

  • 避免在属性设置中通过函数判断模式(如getResource()返回色值),因热更新场景下,属性代码可能不重新执行,导致适配失效,示例:
// 不推荐:依赖属性重新执行,可靠性低
getResource(): string { return colorMode === "dark" ? "#000000" : "#FFFFFF"; }
Button.backgroundColor(this.getResource())

六、优化深浅色模式切换开销(API 20+)

默认切换需全量重绘,性能随 UI 复杂度上升,可通过metadata配置开启高性能切换:

  1. module.json5中新增配置:
"metadata": [
  { "name": "configColorModeChangePerformanceInArkUI", "value": "true" }
]
  1. 注意:开启前需确保所有 “函数适配深浅色” 的逻辑已整改(避免逻辑失效)。

七、反色能力快速适配(API 20+)

适用于存量代码多、需快速适配深色的场景,基于 “优化切换开销” 开启,通过反色算法自动调整颜色,无需大量资源配置:

  1. 核心接口OH_ArkUI_SetForceDarkConfig,支持系统默认反色 / 自定义反色算法,仅对 “非资源值设置的颜色属性” 生效(资源配置优先);
  2. 调用要求
    • 需先加载OH_ArkUI_QueryModuleInterfaceByName(ARKUI_NATIVE_NODE, "ArkUI_NativeNodeAPI_1")
    • 在 UI 线程、节点创建前调用;
    • 仅进程级生效,不支持部分组件单独启用 / 禁用(如全局禁用则所有组件禁用);
  3. 生效优先级:开发者深色资源 > 控件级反色算法 > 全局反色算法;
  4. 不支持场景DatePickerDialog/TimePickerDialog等无实体节点的组件、CAPI 创建的节点。

【官方文档示例详解】

【问题分析】

实现HarmonyOS的深色模式以下方式。

【技术方案】

  1. 颜色适配

    • 自定义资源实现 resources目录下增加深色模式限定词目录(命名为dark)并新建color.json文件,可显示深色模式颜色资源的配置。详细请参考资源分类与访问

      图1 resources目录结构示意

      resources目录结构示意

      例如,你可以在这两个color.json中定义同名配色定义并赋予不同的色值。

      base/element/color.json文件:

      {
      "color": [
      {
      "name": "app_title_color",
      "value": "#000000"
      }
      ]
      }
      
  2. 通过系统资源实现 开发者可直接使用的系统预置资源,即分层参数,同一资源ID在设备类型、深浅色等不同配置下有不同的取值。通过使用系统资源,不同的开发者可以开发出具有相同视觉风格的应用,不需要自定义两份颜色资源,在深浅色模式下也会自动切换成不同的颜色值。例如,开发者可调用系统资源中的文本主要配色来定义应用内文本颜色。

    Text('使用系统定义配色')
    .fontColor($r('sys.color.ohos_id_color_text_primary'))
    

    详细的文档可以使用:https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/ui-dark-light-color-adaptation#%E5%BA%94%E7%94%A8%E8%B7%9F%E9%9A%8F%E7%B3%BB%E7%BB%9F%E7%9A%84%E6%B7%B1%E6%B5%85%E8%89%B2%E6%A8%A1%E5%BC%8F

有要学HarmonyOS AI的同学吗,联系我:https://www.itying.com/goods-1206.html

使用colorMode

使用环境变量获取colorMode

根据参考文档,系统存在深浅色两种显示模式,分为下面两种情况:

  1. 应用跟随系统的深浅色模式
  2. 应用主动设置深浅色模式

不是有快捷吗,

鸿蒙Next深色模式适配使用资源限定符和主题切换。在resources目录下创建dark.element和dark.pattern文件定义深色样式,通过"ohos:colorMode"属性配置。在Ability中使用setTheme()方法动态切换主题,或通过config.json配置系统跟随。使用@ohos.app.ability.common模块检测系统主题变化,调用onConfigurationUpdate回调更新界面。需为所有自定义组件定义深色模式下的颜色和图片资源。

在HarmonyOS Next中适配深色模式,主要通过资源管理和主题响应机制实现:

  1. 资源目录配置
    resources目录下分别创建:

    • base/element/(默认主题)
    • dark/element/(深色主题) 在对应目录中定义颜色值(如color.json)和样式,系统会根据主题自动切换。
  2. 动态颜色定义
    使用资源引用符$color:定义颜色,例如:

    {
      "color": [
        { "name": "background_color", "value": "$color:ffffff" },
        { "name": "text_primary", "value": "$color:000000" }
      ]
    }
    

    深色模式下在dark/element/color.json中覆盖为深色值。

  3. UI组件自适应
    直接引用资源名的组件会自动响应主题变化:

    Text('示例文本')
      .fontColor($r('app.color.text_primary'))
      .backgroundColor($r('app.color.background_color'))
    
  4. 手动监听主题变化
    通过window.getLastWindow(ctx)获取窗口实例,监听colorModeChange事件:

    window.getLastWindow(ctx).on('colorModeChange', (newMode) => {
      // 根据newMode更新UI逻辑
    });
    
  5. 深色模式标识
    使用Configuration模块检测当前模式:

    import configuration from '[@ohos](/user/ohos).app.ability.Configuration';
    const config: Configuration = context.config;
    const isDark = (config.colorMode === ColorMode.COLOR_MODE_DARK);
    

建议在开发阶段同时测试浅色/深色主题,确保文字对比度、图标清晰度等符合用户体验规范。具体可参考官方文档《暗色模式适配指导》。

回到顶部