深色模式与字体缩放 — 鸿蒙应用的视觉一致性保障

在这里插入图片描述

文章简介

现代操作系统都提供了深色模式和字体缩放等无障碍功能,应用需要正确适配这些系统级别的显示设置,以保证视觉一致性和可用性。HarmonyOS 通过 dark 资源目录、@ohos.config 配置变更监听等机制支持深色模式适配。MoneyTrack 在 app_setting 示例组件中展示了深色模式和字体放大的配置方法,本文系统介绍适配策略,涵盖资源覆盖机制、配置监听 API、字体缩放适配和系统符号表现等关键主题。

深色模式的资源覆盖机制

HarmonyOS 的资源管理系统采用限定符机制,应用在 resources 目录下创建带有限定符的子目录,系统会根据当前配置自动选择对应的资源文件。深色模式下的资源覆盖流程如下:

渲染错误: Mermaid 渲染失败: Parse error on line 5: ... C -->|方式二:代码监听| E[@ohos.config.on

系统在深色模式启动时自动加载 dark 目录下的资源,覆盖 base 目录的默认值,应用无需任何额外代码即可实现基础适配。

核心知识点

1. dark 资源目录配置

HarmonyOS 支持通过资源目录限定符来实现深色模式资源切换。在 resources 目录下创建 dark 限定符子目录(如 resources/base/dark/element/),放入深色模式下使用的颜色值。dark 限定符还可以与其他限定符组合使用,实现更细粒度的控制:

resources/
├── base/
│   └── element/
│       ├── color.json          # 浅色模式颜色
│       └── string.json
├── dark/
│   └── element/
│       └── color.json          # 深色模式颜色(同名覆盖)
├── dark-phone/                  # 深色 + 手机限定
│   └── element/
│       └── color.json
└── dark-tablet/                 # 深色 + 平板限定
    └── element/
        └── color.json
// resources/base/element/color.json — 浅色模式
{
  "color": [
    { "name": "font_color_level1", "value": "#ff000000" },
    { "name": "font_color_level2", "value": "#ff666666" },
    { "name": "bg_color_primary", "value": "#fff5f5f5" },
    { "name": "card_bg_color", "value": "#ffffffff" }
  ]
}

// resources/dark/element/color.json — 深色模式(同名覆盖)
{
  "color": [
    { "name": "font_color_level1", "value": "#fff2f2f2" },
    { "name": "font_color_level2", "value": "#ff999999" },
    { "name": "bg_color_primary", "value": "#ff1a1a1a" },
    { "name": "card_bg_color", "value": "#ff2d2d2d" }
  ]
}

通过 dark-phonedark-tablet 的组合限定符,可以为手机和平板分别定义深色模式下的颜色值,实现更精细的适配。

2. @ohos.config 完整 API

HarmonyOS 提供了 @ohos.config 模块,可以监听系统配置变化。以下是完整的配置监听示例:

import { config } from '@ohos.config';

// 监听深色模式切换
config.on('darkModeChange', (isDark: boolean) => {
  console.info(`深色模式状态变更:${isDark}`);
  // 更新 UI 主题(对于无法通过资源文件自动适配的场景)
  if (isDark) {
    // 手动设置深色主题
  } else {
    // 手动设置浅色主题
  }
});

// 监听字体缩放比例变化
config.on('fontScaleChange', (fontScale: number) => {
  console.info(`字体缩放比例变更:${fontScale}`);
  // fontScale 范围通常为 0.85~1.3
  // 根据缩放比例调整布局,避免文字溢出
  if (fontScale > 1.2) {
    // 大字体模式下调整布局
  }
});

// 同时监听多个配置变更
config.on('configurationUpdate', (cfg: config.Configuration) => {
  // darkMode: boolean — 是否深色模式
  // fontScale: number — 字体缩放比例
  // fontSize: number — 字体大小
  console.info(`配置更新:${JSON.stringify(cfg)}`);
});

3. 字体缩放适配

鸿蒙系统支持用户设置字体缩放比例(通常为 0.85~1.3 倍),应用应使用 vp 单位而非固定的 fp 单位,并避免在重要布局中使用固定尺寸的文字区域。以下是对字体缩放的完整适配方案:

@Component
export struct ScalableText {
  @State fontSize: number = 16;  // 基础字号,单位 fp

  build() {
    Column() {
      // 方式一:使用 fp 单位(推荐,自动跟随系统字体缩放)
      Text('使用 fp 单位自动缩放')
        .fontSize(16)
        .width('100%')

      // 方式二:手动获取系统字体缩放比例进行调整
      Text('手动适配:当前缩放 ' + this.getFontScale())
        .fontSize(this.getScaledSize(16))

      // 方式三:对重要描述文字允许用户单独设置
      Text('用户自定义大小')
        .fontSize(this.userFontSize)
    }
    .width('100%')
    .padding(10)
  }

  getFontScale(): number {
    // 通过 UIContext 获取系统字体缩放
    return this.getUIContext()?.getFontScale() ?? 1.0;
  }

  getScaledSize(baseFp: number): number {
    return baseFp * this.getFontScale();
  }
}

4. 系统符号在深色模式下的表现

使用系统内置图标时,在深色模式下通常不需要额外处理——系统符号会自动适配当前主题的颜色。但需要注意以下几点:

// 系统符号自动适配深浅色模式
SymbolGlyph({ name: 'magnifier' })
  .fontSize(24)
  // 无需额外设置颜色,系统自动处理

// 如果自定义符号颜色,则需要考虑深浅色切换
Image($r('app.media.ic_custom_icon'))
  .colorFilter(this.isDarkMode ?
    [0.8, 0, 0, 0, 0,   0, 0.8, 0, 0, 0,   0, 0, 0.8, 0, 0,   0, 0, 0, 1, 0] :
    [1, 0, 0, 0, 0,   0, 1, 0, 0, 0,   0, 0, 1, 0, 0,   0, 0, 0, 1, 0]
  )
// 建议:优先使用系统符号,或通过 $r('app.media.icon_dark') 和
// $r('app.media.icon_light') 分别配置深浅色图标

项目代码案例

app_setting 组件对深色模式和字体放大支持的示例配置

文件路径:components/app_setting/

app_setting 模块提供了深色模式和字体缩放的示例配置。通过 resource 目录下的 dark 限定符,颜色值在不同模式下自动切换。

module.json5 中声明支持深色模式:

{
  "module": {
    "abilities": [
      {
        "name": "EntryAbility",
        "darkMode": "auto"   // auto:跟随系统, always:始终深色, never:始终浅色
      }
    ]
  }
}

在代码中通过 $r('app.color.font_color_level1') 引用颜色资源,系统会根据当前主题自动选择合适的颜色值。

最佳实践

维度 建议 说明
资源管理 优先使用 dark 限定符资源覆盖 无需额外代码,系统自动切换
组合限定符 使用 dark-phone、dark-tablet 组合 适配不同设备类型的深色视觉差异
配置监听 注册 configurationUpdate 监听 统一处理所有配置变更
字体单位 使用 fp 单位,配合 vp 进行布局 fp 自动跟随系统字体缩放
布局检查 在大字体模式下验证文字溢出 设置 maxLines 约束或可滚动容器
系统符号 优先使用 SymbolGlyph 组件 自动适配深浅色,无需额外处理
测试覆盖 切换深浅色模式 + 最大最小字体 确保所有页面的视觉完整性

推荐参考文档

  • HarmonyOS 深色模式开发指南
  • resource 限定符目录命名规范
  • @ohos.config 系统配置 API
  • ArkUI vp/fp 单位使用说明
  • SymbolGlyph 系统符号组件文档
  • app_setting 模块代码示例
Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐