【OpenHarmony/HarmonyOs 】49|资源化颜色主题:从硬编码色值到深色模式自动适配 🎨

本文基于当前项目 resources/base/element/color.jsonresources/dark/element/color.jsonLoginPage.etsMainPage.etsMoodPage.etsChatDetailPage.ets 的真实实现展开。
项目已经为启动窗口准备了明暗资源,但业务页面仍存在大量十六进制与 rgba 硬编码;本文给出不破坏现有主题切换功能的渐进式资源化方案。

一、为什么颜色资源化不是简单的字符串替换?

当前项目同时存在三类颜色来源:

  • 启动窗口使用 $color:start_window_background
  • 页面使用 readonly primaryColor: string = '#009688'
  • 聊天详情使用 ChatTheme 保存多套业务主题。

三者分别对应系统资源、页面常量与用户可选主题。

如果把所有色值一次性替换成同一个资源,会破坏聊天主题;如果只处理背景色,又可能让深色模式下文字失去对比度。

正确目标不是“代码里看不到 #”,而是建立清晰的颜色语义、资源覆盖关系与主题边界。


二、项目当前的真实资源基础

基础资源只有启动背景:

{
  "color": [
    {
      "name": "start_window_background",
      "value": "#FFFFFF"
    }
  ]
}

深色目录使用相同资源名提供覆盖值:

{
  "color": [
    {
      "name": "start_window_background",
      "value": "#000000"
    }
  ]
}

这已经证明项目具备资源限定目录的正确入口。

真正缺失的是业务语义色:页面背景、卡片背景、主要文字、次要文字、分割线、品牌色、危险色与遮罩色。


三、硬编码颜色带来的真实问题

LoginPageMainPageMoodPage 都直接声明了薄荷主题色。

readonly primaryColor: string = '#009688';
readonly bgColor: string = '#F5F7FA';
readonly textColor: string = '#37474F';

这种写法在浅色模式下直观,但系统切换深色模式时不会自动变化。

更隐蔽的问题是半透明白色卡片:

.backgroundColor('rgba(255, 255, 255, 0.7)')

深色背景上继续叠加白色玻璃层,会产生突兀亮块。

因此迁移必须同时覆盖实体色、透明色、阴影色与状态色。


四、先建立语义色,而不是按色值命名

不推荐以下命名:

  • white
  • gray_100
  • teal_500
  • color_01

推荐以下命名:

  • page_background
  • surface_primary
  • surface_secondary
  • text_primary
  • text_secondary
  • divider_color
  • brand_primary
  • danger_color

语义命名表达“颜色负责什么”,而不是“颜色现在长什么样”。


五、推荐的基础资源结构

浅色资源可以扩展为:

{
  "color": [
    { "name": "start_window_background", "value": "#FFFFFF" },
    { "name": "page_background", "value": "#F5F7FA" },
    { "name": "surface_primary", "value": "#FFFFFF" },
    { "name": "surface_secondary", "value": "#E0F2F1" },
    { "name": "text_primary", "value": "#37474F" },
    { "name": "text_secondary", "value": "#78909C" },
    { "name": "brand_primary", "value": "#009688" },
    { "name": "divider_color", "value": "#EEEEEE" },
    { "name": "danger_color", "value": "#FF7043" }
  ]
}

深色资源保持同名,只替换值:

{
  "color": [
    { "name": "start_window_background", "value": "#000000" },
    { "name": "page_background", "value": "#101414" },
    { "name": "surface_primary", "value": "#1A2222" },
    { "name": "surface_secondary", "value": "#203634" },
    { "name": "text_primary", "value": "#E8F0EF" },
    { "name": "text_secondary", "value": "#A7B8B6" },
    { "name": "brand_primary", "value": "#4DB6AC" },
    { "name": "divider_color", "value": "#33403F" },
    { "name": "danger_color", "value": "#FF8A65" }
  ]
}

系统会根据当前颜色模式解析同名资源,页面不需要手写模式判断。


六、ArkUI 页面如何引用颜色资源?

组件属性直接使用 $r

.backgroundColor($r('app.color.page_background'))
.fontColor($r('app.color.text_primary'))
.border({ width: 1, color: $r('app.color.divider_color') })

当属性接受 ResourceColor 时,应优先保留资源对象,不要提前转为字符串。

错误做法是读取资源后拼接透明度字符串,因为这会重新退化为运行时色值处理。


七、颜色类型要跟着资源化调整

项目中的 ChatTheme.headerBg 已经使用:

headerBg: string | Resource;

但其他字段仍是 string

如果主题字段允许资源,应统一考虑 ResourceColor 或项目当前 API 支持的兼容类型。

不要在调用处大量使用 as string,否则类型声明虽然支持资源,实际代码仍强迫它成为字符串。


八、系统深色模式与聊天业务主题不是一回事

系统模式回答:当前环境适合浅色还是深色。

聊天主题回答:用户想使用薄荷、暖色还是粉色。

推荐分层:

  1. 系统资源提供基础页面、文字、边框和遮罩;
  2. 聊天主题只覆盖头部、气泡、发送按钮等品牌化区域;
  3. 每套聊天主题都需要浅色与深色可读性验证;
  4. 未被业务主题覆盖的区域继续使用系统语义资源。

这样既保留现有换肤能力,又能响应系统颜色模式。


九、不要强制锁定颜色模式

EntryAbility 当前调用:

this.context.getApplicationContext().setColorMode(
  ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET
);

COLOR_MODE_NOT_SET 的方向是让应用遵循系统配置。

如果页面颜色仍全部硬编码,遵循系统也不会产生完整效果。

资源化迁移完成后,这个入口才能真正发挥作用。


十、渐进迁移顺序

建议按风险从低到高迁移:

  1. 页面大背景;
  2. 主次文字;
  3. 卡片与分割线;
  4. 普通按钮与图标;
  5. 阴影和半透明玻璃层;
  6. 聊天气泡与动态主题;
  7. 图表、热力图和渐变。

每完成一类都应在浅色、深色和高对比场景核验。


十一、资源化实施核验清单

检查项 1:资源命名

  • 检查目标:颜色名表达页面语义。
  • 常见反例:出现 white、gray 或 color01 等外观命名。
  • 推荐动作:重命名为 page、surface、text、brand 等职责名称。
  • 验证环境:浅色模式、深色模式、运行中切换与冷启动。
  • 通过标准:界面语义一致、文字可读、状态可辨且没有新增硬编码。

检查项 2:同名覆盖

  • 检查目标:base 与 dark 使用完全相同的资源名。
  • 常见反例:深色目录另起一套 dark_xxx 名称。
  • 推荐动作:让资源系统自动选择,不在页面判断模式。
  • 验证环境:浅色模式、深色模式、运行中切换与冷启动。
  • 通过标准:界面语义一致、文字可读、状态可辨且没有新增硬编码。

检查项 3:页面背景

  • 检查目标:根容器使用 page_background。
  • 常见反例:继续写死 #F5F7FA。
  • 推荐动作:先迁移最稳定、覆盖面积最大的背景色。
  • 验证环境:浅色模式、深色模式、运行中切换与冷启动。
  • 通过标准:界面语义一致、文字可读、状态可辨且没有新增硬编码。

检查项 4:主要文字

  • 检查目标:标题和正文使用 text_primary。
  • 常见反例:深色模式仍显示 #37474F。
  • 推荐动作:验证普通字号下的对比度。
  • 验证环境:浅色模式、深色模式、运行中切换与冷启动。
  • 通过标准:界面语义一致、文字可读、状态可辨且没有新增硬编码。

检查项 5:次要文字

  • 检查目标:辅助信息使用 text_secondary。
  • 常见反例:为了显得柔和而降低到不可读。
  • 推荐动作:在真实设备与低亮度环境检查。
  • 验证环境:浅色模式、深色模式、运行中切换与冷启动。
  • 通过标准:界面语义一致、文字可读、状态可辨且没有新增硬编码。

检查项 6:卡片表面

  • 检查目标:卡片使用 surface_primary。
  • 常见反例:把所有白色都替换成同一背景色。
  • 推荐动作:区分页面层与浮层层级。
  • 验证环境:浅色模式、深色模式、运行中切换与冷启动。
  • 通过标准:界面语义一致、文字可读、状态可辨且没有新增硬编码。

检查项 7:次级表面

  • 检查目标:标签和选中态使用 surface_secondary。
  • 常见反例:直接复用品牌色导致面积过重。
  • 推荐动作:用柔和表面承载弱强调。
  • 验证环境:浅色模式、深色模式、运行中切换与冷启动。
  • 通过标准:界面语义一致、文字可读、状态可辨且没有新增硬编码。

检查项 8:分割线

  • 检查目标:边界使用 divider_color。
  • 常见反例:深色模式仍用 #EEEEEE。
  • 推荐动作:控制边界可见但不过度抢眼。
  • 验证环境:浅色模式、深色模式、运行中切换与冷启动。
  • 通过标准:界面语义一致、文字可读、状态可辨且没有新增硬编码。

检查项 9:品牌色

  • 检查目标:主要动作使用 brand_primary。
  • 常见反例:每个页面复制 #009688。
  • 推荐动作:统一品牌入口并允许深色提亮。
  • 验证环境:浅色模式、深色模式、运行中切换与冷启动。
  • 通过标准:界面语义一致、文字可读、状态可辨且没有新增硬编码。

检查项 10:危险色

  • 检查目标:删除和失败状态使用 danger_color。
  • 常见反例:把业务失败与普通品牌色混用。
  • 推荐动作:保持跨页面状态语义一致。
  • 验证环境:浅色模式、深色模式、运行中切换与冷启动。
  • 通过标准:界面语义一致、文字可读、状态可辨且没有新增硬编码。

检查项 11:阴影色

  • 检查目标:阴影资源按模式调整透明度。
  • 常见反例:深色模式继续使用浅色外发光。
  • 推荐动作:深色环境优先用层级与描边。
  • 验证环境:浅色模式、深色模式、运行中切换与冷启动。
  • 通过标准:界面语义一致、文字可读、状态可辨且没有新增硬编码。

检查项 12:遮罩色

  • 检查目标:弹层遮罩拥有独立语义。
  • 常见反例:把纯黑透明值散落各页面。
  • 推荐动作:统一遮罩强度并验证可关闭区域。
  • 验证环境:浅色模式、深色模式、运行中切换与冷启动。
  • 通过标准:界面语义一致、文字可读、状态可辨且没有新增硬编码。

检查项 13:透明卡片

  • 检查目标:玻璃层在两种模式都有资源方案。
  • 常见反例:固定 rgba(255,255,255,0.7)。
  • 推荐动作:深色模式改用深色半透明表面。
  • 验证环境:浅色模式、深色模式、运行中切换与冷启动。
  • 通过标准:界面语义一致、文字可读、状态可辨且没有新增硬编码。

检查项 14:渐变起点

  • 检查目标:渐变端点由语义资源控制。
  • 常见反例:组件内部直接写多个十六进制值。
  • 推荐动作:明确渐变是品牌还是状态表达。
  • 验证环境:浅色模式、深色模式、运行中切换与冷启动。
  • 通过标准:界面语义一致、文字可读、状态可辨且没有新增硬编码。

检查项 15:图标颜色

  • 检查目标:普通图标跟随 text_secondary。
  • 常见反例:图标固定黑色或白色。
  • 推荐动作:让图标与相邻文字保持同级。
  • 验证环境:浅色模式、深色模式、运行中切换与冷启动。
  • 通过标准:界面语义一致、文字可读、状态可辨且没有新增硬编码。

检查项 16:禁用状态

  • 检查目标:禁用前景和背景分别定义。
  • 常见反例:只通过 opacity 处理所有禁用效果。
  • 推荐动作:检查文字仍然可读且状态明确。
  • 验证环境:浅色模式、深色模式、运行中切换与冷启动。
  • 通过标准:界面语义一致、文字可读、状态可辨且没有新增硬编码。

检查项 17:选中状态

  • 检查目标:选中态使用品牌语义。
  • 常见反例:仅靠颜色表达选中。
  • 推荐动作:同时增加字重、图标或形状提示。
  • 验证环境:浅色模式、深色模式、运行中切换与冷启动。
  • 通过标准:界面语义一致、文字可读、状态可辨且没有新增硬编码。

检查项 18:焦点状态

  • 检查目标:键盘焦点边框可见。
  • 常见反例:深色主题下焦点环消失。
  • 推荐动作:为焦点建立独立高对比资源。
  • 验证环境:浅色模式、深色模式、运行中切换与冷启动。
  • 通过标准:界面语义一致、文字可读、状态可辨且没有新增硬编码。

检查项 19:链接颜色

  • 检查目标:链接与正文有稳定区分。
  • 常见反例:链接直接复用浅色品牌值。
  • 推荐动作:验证已访问、按压和禁用状态。
  • 验证环境:浅色模式、深色模式、运行中切换与冷启动。
  • 通过标准:界面语义一致、文字可读、状态可辨且没有新增硬编码。

检查项 20:输入框

  • 检查目标:输入背景、文字、占位符分开定义。
  • 常见反例:所有文字共用一个灰色。
  • 推荐动作:保证输入内容优先级最高。
  • 验证环境:浅色模式、深色模式、运行中切换与冷启动。
  • 通过标准:界面语义一致、文字可读、状态可辨且没有新增硬编码。

检查项 21:错误输入

  • 检查目标:错误边框与错误文案一致。
  • 常见反例:只改变边框且无文字说明。
  • 推荐动作:颜色之外提供明确错误描述。
  • 验证环境:浅色模式、深色模式、运行中切换与冷启动。
  • 通过标准:界面语义一致、文字可读、状态可辨且没有新增硬编码。

检查项 22:状态栏

  • 检查目标:顶部区域与页面背景协调。
  • 常见反例:页面深色但状态栏图标不可见。
  • 推荐动作:联动窗口样式与安全区背景。
  • 验证环境:浅色模式、深色模式、运行中切换与冷启动。
  • 通过标准:界面语义一致、文字可读、状态可辨且没有新增硬编码。

检查项 23:导航栏

  • 检查目标:底部栏使用独立 surface 语义。
  • 常见反例:直接写死白色 TabBar。
  • 推荐动作:检查选中与未选中图标对比。
  • 验证环境:浅色模式、深色模式、运行中切换与冷启动。
  • 通过标准:界面语义一致、文字可读、状态可辨且没有新增硬编码。

检查项 24:启动窗口

  • 检查目标:启动背景与首屏背景连续。
  • 常见反例:启动白屏后瞬间切深色。
  • 推荐动作:让 start_window_background 对应首屏。
  • 验证环境:浅色模式、深色模式、运行中切换与冷启动。
  • 通过标准:界面语义一致、文字可读、状态可辨且没有新增硬编码。

检查项 25:聊天头部

  • 检查目标:业务主题只覆盖约定区域。
  • 常见反例:主题对象控制整个应用基础颜色。
  • 推荐动作:限制主题影响范围,避免耦合。
  • 验证环境:浅色模式、深色模式、运行中切换与冷启动。
  • 通过标准:界面语义一致、文字可读、状态可辨且没有新增硬编码。

检查项 26:聊天气泡

  • 检查目标:自己与对方气泡均有前景色。
  • 常见反例:只换气泡背景不换文字。
  • 推荐动作:成对验证背景与文字资源。
  • 验证环境:浅色模式、深色模式、运行中切换与冷启动。
  • 通过标准:界面语义一致、文字可读、状态可辨且没有新增硬编码。

检查项 27:聊天选择器

  • 检查目标:主题预览在深色模式可识别。
  • 常见反例:预览卡固定 #F5F5F5。
  • 推荐动作:预览容器使用系统表面资源。
  • 验证环境:浅色模式、深色模式、运行中切换与冷启动。
  • 通过标准:界面语义一致、文字可读、状态可辨且没有新增硬编码。

检查项 28:热力图

  • 检查目标:数据色阶与无数据色分离。
  • 常见反例:浅色低值格在深色背景消失。
  • 推荐动作:为图表建立独立数据调色板。
  • 验证环境:浅色模式、深色模式、运行中切换与冷启动。
  • 通过标准:界面语义一致、文字可读、状态可辨且没有新增硬编码。

检查项 29:趋势图

  • 检查目标:折线与网格线分别资源化。
  • 常见反例:网格线固定 #EEEEEE。
  • 推荐动作:控制辅助线弱于数据线。
  • 验证环境:浅色模式、深色模式、运行中切换与冷启动。
  • 通过标准:界面语义一致、文字可读、状态可辨且没有新增硬编码。

检查项 30:情绪色

  • 检查目标:业务情绪色不冒充系统状态色。
  • 常见反例:开心绿色同时表示请求成功。
  • 推荐动作:区分业务数据颜色与交互反馈。
  • 验证环境:浅色模式、深色模式、运行中切换与冷启动。
  • 通过标准:界面语义一致、文字可读、状态可辨且没有新增硬编码。

检查项 31:资源类型

  • 检查目标:属性保持 Resource 或 ResourceColor。
  • 常见反例:到处使用 as string。
  • 推荐动作:让编译器检查资源用法。
  • 验证环境:浅色模式、深色模式、运行中切换与冷启动。
  • 通过标准:界面语义一致、文字可读、状态可辨且没有新增硬编码。

检查项 32:方法参数

  • 检查目标:Builder 参数接受正确颜色类型。
  • 常见反例:资源传入后被限制为 string。
  • 推荐动作:从公共组件边界完成类型迁移。
  • 验证环境:浅色模式、深色模式、运行中切换与冷启动。
  • 通过标准:界面语义一致、文字可读、状态可辨且没有新增硬编码。

检查项 33:数组模型

  • 检查目标:主题数组字段类型统一。
  • 常见反例:部分字段支持 Resource、部分强转。
  • 推荐动作:定义明确主题接口并逐字段核验。
  • 验证环境:浅色模式、深色模式、运行中切换与冷启动。
  • 通过标准:界面语义一致、文字可读、状态可辨且没有新增硬编码。

检查项 34:回退策略

  • 检查目标:缺失资源时构建阶段即可发现。
  • 常见反例:运行时静默回退到硬编码。
  • 推荐动作:依赖资源校验而非隐藏问题。
  • 验证环境:浅色模式、深色模式、运行中切换与冷启动。
  • 通过标准:界面语义一致、文字可读、状态可辨且没有新增硬编码。

检查项 35:多模块资源

  • 检查目标:明确 app 与 module 资源作用域。
  • 常见反例:跨模块复制同名不同义资源。
  • 推荐动作:公共语义放在可复用模块。
  • 验证环境:浅色模式、深色模式、运行中切换与冷启动。
  • 通过标准:界面语义一致、文字可读、状态可辨且没有新增硬编码。

检查项 36:命名冲突

  • 检查目标:同类型资源名全局唯一且语义一致。
  • 常见反例:同名资源在不同位置表达不同职责。
  • 推荐动作:建立资源命名词典。
  • 验证环境:浅色模式、深色模式、运行中切换与冷启动。
  • 通过标准:界面语义一致、文字可读、状态可辨且没有新增硬编码。

检查项 37:资源审计

  • 检查目标:定期搜索十六进制与 rgba。
  • 常见反例:只靠人工浏览页面。
  • 推荐动作:使用检索结果建立迁移清单。
  • 验证环境:浅色模式、深色模式、运行中切换与冷启动。
  • 通过标准:界面语义一致、文字可读、状态可辨且没有新增硬编码。

检查项 38:例外登记

  • 检查目标:确需动态计算的颜色有明确理由。
  • 常见反例:任何硬编码都以动画为借口保留。
  • 推荐动作:记录例外、负责人和复查时间。
  • 验证环境:浅色模式、深色模式、运行中切换与冷启动。
  • 通过标准:界面语义一致、文字可读、状态可辨且没有新增硬编码。

检查项 39:浅色测试

  • 检查目标:常用页面在浅色完整走查。
  • 常见反例:只看设计稿截图。
  • 推荐动作:覆盖登录、聊天、心情和个人页。
  • 验证环境:浅色模式、深色模式、运行中切换与冷启动。
  • 通过标准:界面语义一致、文字可读、状态可辨且没有新增硬编码。

检查项 40:深色测试

  • 检查目标:系统深色下完整走查。
  • 常见反例:只切换模拟器不操作弹层。
  • 推荐动作:覆盖滚动、输入、弹窗和错误态。
  • 验证环境:浅色模式、深色模式、运行中切换与冷启动。
  • 通过标准:界面语义一致、文字可读、状态可辨且没有新增硬编码。

检查项 41:跟随系统

  • 检查目标:运行中切换模式可正确刷新。
  • 常见反例:必须重启后才显示新资源。
  • 推荐动作:检查资源引用是否被转成固定字符串。
  • 验证环境:浅色模式、深色模式、运行中切换与冷启动。
  • 通过标准:界面语义一致、文字可读、状态可辨且没有新增硬编码。

检查项 42:冷启动

  • 检查目标:深色冷启动无白色闪烁。
  • 常见反例:启动页和首屏资源不一致。
  • 推荐动作:同时核验启动背景与页面背景。
  • 验证环境:浅色模式、深色模式、运行中切换与冷启动。
  • 通过标准:界面语义一致、文字可读、状态可辨且没有新增硬编码。

检查项 43:前后台

  • 检查目标:后台切换模式后返回可刷新。
  • 常见反例:缓存旧主题对象。
  • 推荐动作:检查生命周期中的主题读取时机。
  • 验证环境:浅色模式、深色模式、运行中切换与冷启动。
  • 通过标准:界面语义一致、文字可读、状态可辨且没有新增硬编码。

检查项 44:字体放大

  • 检查目标:大字号下颜色层级仍清晰。
  • 常见反例:依赖小字号和低对比维持布局。
  • 推荐动作:联合可访问性测试。
  • 验证环境:浅色模式、深色模式、运行中切换与冷启动。
  • 通过标准:界面语义一致、文字可读、状态可辨且没有新增硬编码。

检查项 45:高亮模式

  • 检查目标:系统强调或高对比场景可用。
  • 常见反例:只追求低对比玻璃效果。
  • 推荐动作:为核心操作保留清晰边界。
  • 验证环境:浅色模式、深色模式、运行中切换与冷启动。
  • 通过标准:界面语义一致、文字可读、状态可辨且没有新增硬编码。

检查项 46:截图对比

  • 检查目标:建立明暗模式基准截图。
  • 常见反例:改完只凭印象判断。
  • 推荐动作:按页面保存前后对照证据。
  • 验证环境:浅色模式、深色模式、运行中切换与冷启动。
  • 通过标准:界面语义一致、文字可读、状态可辨且没有新增硬编码。

检查项 47:真实设备

  • 检查目标:OLED 与 LCD 均检查。
  • 常见反例:只在单一模拟器验证。
  • 推荐动作:观察纯黑、暗灰与低亮度表现。
  • 验证环境:浅色模式、深色模式、运行中切换与冷启动。
  • 通过标准:界面语义一致、文字可读、状态可辨且没有新增硬编码。

检查项 48:性能检查

  • 检查目标:资源读取不在高频循环中重复包装。
  • 常见反例:列表每项执行复杂颜色转换。
  • 推荐动作:直接传递资源或预先准备模型。
  • 验证环境:浅色模式、深色模式、运行中切换与冷启动。
  • 通过标准:界面语义一致、文字可读、状态可辨且没有新增硬编码。

检查项 49:列表稳定

  • 检查目标:ForEach key 不因主题切换变化。
  • 常见反例:颜色进入 key 导致整表重建。
  • 推荐动作:key 只使用业务唯一标识。
  • 验证环境:浅色模式、深色模式、运行中切换与冷启动。
  • 通过标准:界面语义一致、文字可读、状态可辨且没有新增硬编码。

检查项 50:状态响应

  • 检查目标:主题变化后 @State 引用链完整。
  • 常见反例:把计算色作为固定 Builder 参数缓存。
  • 推荐动作:让 UI 直接消费响应式状态或资源。
  • 验证环境:浅色模式、深色模式、运行中切换与冷启动。
  • 通过标准:界面语义一致、文字可读、状态可辨且没有新增硬编码。

检查项 51:发布检查

  • 检查目标:release 包核验资源未被错误裁剪。
  • 常见反例:只验证 debug。
  • 推荐动作:检查资源引用与混淆配置。
  • 验证环境:浅色模式、深色模式、运行中切换与冷启动。
  • 通过标准:界面语义一致、文字可读、状态可辨且没有新增硬编码。

检查项 52:回归范围

  • 检查目标:迁移不改变点击、路由和数据逻辑。
  • 常见反例:顺手重构业务代码。
  • 推荐动作:一次提交只处理可验证的颜色范围。
  • 验证环境:浅色模式、深色模式、运行中切换与冷启动。
  • 通过标准:界面语义一致、文字可读、状态可辨且没有新增硬编码。

检查项 53:设计协作

  • 检查目标:语义色表与设计规范一致。
  • 常见反例:开发自行新增近似色。
  • 推荐动作:新颜色先归类再进入资源。
  • 验证环境:浅色模式、深色模式、运行中切换与冷启动。
  • 通过标准:界面语义一致、文字可读、状态可辨且没有新增硬编码。

检查项 54:国际化

  • 检查目标:颜色不依赖中文文案长度。
  • 常见反例:深色下长英文被背景裁切。
  • 推荐动作:联合中英文与大字号检查。
  • 验证环境:浅色模式、深色模式、运行中切换与冷启动。
  • 通过标准:界面语义一致、文字可读、状态可辨且没有新增硬编码。

检查项 55:可访问性

  • 检查目标:关键信息不只靠红绿区分。
  • 常见反例:成功失败仅改变颜色。
  • 推荐动作:增加图标、文本和状态描述。
  • 验证环境:浅色模式、深色模式、运行中切换与冷启动。
  • 通过标准:界面语义一致、文字可读、状态可辨且没有新增硬编码。

检查项 56:文档同步

  • 检查目标:资源名含义可从代码直接理解。
  • 常见反例:依赖口头约定。
  • 推荐动作:通过稳定命名减少额外文档成本。
  • 验证环境:浅色模式、深色模式、运行中切换与冷启动。
  • 通过标准:界面语义一致、文字可读、状态可辨且没有新增硬编码。

检查项 57:代码评审

  • 检查目标:新增硬编码颜色会被指出。
  • 常见反例:资源化只做一次专项。
  • 推荐动作:把语义色检查纳入日常评审。
  • 验证环境:浅色模式、深色模式、运行中切换与冷启动。
  • 通过标准:界面语义一致、文字可读、状态可辨且没有新增硬编码。

检查项 58:迁移节奏

  • 检查目标:按页面小步替换并构建。
  • 常见反例:一次替换全项目所有色值。
  • 推荐动作:每批保持可回滚与可定位。
  • 验证环境:浅色模式、深色模式、运行中切换与冷启动。
  • 通过标准:界面语义一致、文字可读、状态可辨且没有新增硬编码。

检查项 59:验收结论

  • 检查目标:每个页面都有明暗模式证据。
  • 常见反例:只统计替换数量。
  • 推荐动作:以用户可读、可操作作为最终标准。
  • 验证环境:浅色模式、深色模式、运行中切换与冷启动。
  • 通过标准:界面语义一致、文字可读、状态可辨且没有新增硬编码。

十二、推荐的落地分支策略

第一批只新增资源,不修改页面。

第二批迁移登录页和主导航,因为它们结构稳定、覆盖面清晰。

第三批迁移心情页的卡片、文字与分割线。

第四批处理聊天详情,并明确系统主题与用户主题的覆盖优先级。

第五批处理图表、透明玻璃层、阴影和渐变等复杂视觉。

每一批都应完成构建、明暗截图对比和主流程回归。


十三、常见反模式速查

反模式 直接后果 正确方向
所有白色替换成一个资源 页面层级消失 区分背景与表面
dark 使用不同资源名 页面必须手动判断模式 同名资源限定覆盖
资源强转 string 丢失资源能力与类型检查 保持 ResourceColor
主题对象控制全应用 业务换肤与系统模式耦合 明确覆盖边界
只迁移实体色 玻璃层和阴影仍然刺眼 同步治理透明色
一次性全局替换 回归范围不可控 按页面渐进迁移
只看浅色设计稿 深色模式不可用 双模式真实设备验收

十四、总结

资源化颜色主题的核心不是把 #009688 搬进 JSON。

真正的工程收益来自三点:

  1. 用语义资源统一页面职责;
  2. 用限定目录自动承接系统深色模式;
  3. 用清晰边界保留聊天等业务换肤能力。

当颜色从“页面里的常量”升级为“系统可解析的设计语义”,深色模式、视觉一致性和后续维护才真正进入可治理状态。

img

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐