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

📅 2026/7/19 2:42:33 👁️ 阅读次数 📝 编程学习
【OpenHarmony/HarmonyOs 】49|资源化颜色主题:从硬编码色值到深色模式自动适配

【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都直接声明了薄荷主题色。

readonlyprimaryColor:string='#009688';readonlybgColor:string='#F5F7FA';readonlytextColor: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. 用清晰边界保留聊天等业务换肤能力。

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