鸿蒙应用开发实战【03】— ArkUI 设计令牌体系构建(颜色/字体/动画)
前言
欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net
在多人协作的项目中,如果每个开发者随意使用颜色字面量('#4F7CFF')、字号(14)、动画时长(300),项目很快就会陷入"颜色一致性噩梦"。**设计令牌(Design Token)**就是解决这个问题的最佳实践——把设计决策集中存储为命名常量,让整个项目通过名字引用而非直接使用原始值。
本篇介绍号码助手项目中的设计令牌体系:AppColors、AppFonts、AppAnimations,以及 ArkUI 中一个极易踩坑的颜色格式问题。
本篇重点:
#AARRGGBB颜色格式、设计令牌封装规范、颜色语义化命名、ArkUI 字体常量、动画曲线封装。
一、为什么需要设计令牌
1.1 没有设计令牌时的问题
// ❌ 没有设计令牌时,颜色散落在各处Text('号码助手').fontColor('#14141E')// 主文字色Text('副标题').fontColor('#14141E80')// 副文字色,但哪个是哪个?.backgroundColor('#B8FFFFFF')// 卡片背景色,什么含义?.border({color:'#14141E14'})// 边框色,语义不明维护困难:设计稿改了主色调,要逐文件搜索替换
1.2 使用设计令牌后
// ✅ 使用设计令牌后,语义清晰Text('号码助手').fontColor(AppColors.TEXT)Text('副标题').fontColor(AppColors.TEXT_2).backgroundColor(AppColors.CARD).border({color:AppColors.LINE})维护简单:改一处AppColors.PRIMARY = '#3A5FD4',全项目生效
二、AppColors — 颜色设计令牌
2.1 完整颜色系统
号码助手使用的完整颜色令牌体系如下:
// AppColors.etsexportclassAppColors{// ── 主色调 ──────────────────────────────────staticreadonlyPRIMARY:string='#4F7CFF'// 主色:蓝紫staticreadonlyPRIMARY_2:string='#7C5CFF'// 辅色:紫staticreadonlyPRIMARY_BG:string='#F0F3FF'// 主色浅背景// ── 功能色 ──────────────────────────────────staticreadonlyDANGER:string='#FF2E4D'// 危险/删除staticreadonlyDANGER_BG:string='#FFF0F2'// 危险背景staticreadonlyWARN:string='#FF7A1E'// 警告/待换绑staticreadonlyWARN_BG:string='#FFF5EE'// 警告背景staticreadonlyCYAN:string='#20C0CE'// 青色/强调// ── 文字色 ──────────────────────────────────staticreadonlyTEXT:string='#14141E'// 主文字(近黑)staticreadonlyTEXT_2:string='#14141E80'// 副文字(半透明)staticreadonlyTEXT_3:string='#14141E4D'// 占位文字staticreadonlyMUTED:string='#999999'// 禁用文字// ── 背景色 ──────────────────────────────────staticreadonlyBG:string='#F5F7FF'// 页面背景staticreadonlyMUTED_BG:string='#F2F2F7'// 灰色背景// ── 卡片与边框(关键!使用 #AARRGGBB 格式)──staticreadonlyCARD:string='#B8FFFFFF'// 毛玻璃卡片(72% 透明度白色)staticreadonlyCARD_B:string='#E6FFFFFF'// 浅色卡片(90% 透明度白色)staticreadonlyLINE:string='#14141E14'// 分割线/边框(8% 透明度黑色)}2.2 颜色分类对照表
| 类别 | 令牌名 | 十六进制值 | 用途 |
|---|---|---|---|
| 主色 | PRIMARY | #4F7CFF | 按钮、强调、主要链接 |
| 辅色 | PRIMARY_2 | #7C5CFF | 渐变终点、次要强调 |
| 危险 | DANGER | #FF2E4D | 删除按钮、错误提示 |
| 警告 | WARN | #FF7A1E | 待换绑状态、橙色提示 |
| 主文字 | TEXT | #14141E | 标题、正文 |
| 副文字 | TEXT_2 | #14141E80 | 说明文字(带 50% 透明度) |
| 页面背景 | BG | #F5F7FF | 所有页面的背景色 |
| 卡片 | CARD | #B8FFFFFF | 列表卡片(毛玻璃效果) |
三、ArkUI 颜色格式深度解析(重要踩坑)
3.1 问题现象
号码助手在开发初期,所有卡片都显示为淡黄色,而设计稿要求是半透明白色。
图1:左图为颜色格式错误时的黄色卡片,右图为修复后的正确半透明白色卡片
3.2 根本原因
ArkUI 的颜色格式与 CSS/Android 不同!
| 平台 | 颜色格式 | Alpha 位置 |
|---|---|---|
| CSS / Web | #RRGGBBAA | 最后 |
| Android XML | #AARRGGBB | 最前 |
| ArkUI | #AARRGGBB | 最前 |
以 72% 透明度的白色为例:
// ❌ 错误写法(CSS 格式,AA 在最后)// #FFFFFF 后面加 B8 表示 72% 不透明度staticreadonlyCARD:string='#FFFFFFB8'// ArkUI 解析为:AA=0xFF(完全不透明), R=0xFF, G=0xFF, B=0xB8// 结果:RGB(255, 255, 184) = 淡黄色!// ✅ 正确写法(ArkUI 格式,AA 在最前)// B8 在最前面表示 72% 不透明度staticreadonlyCARD:string='#B8FFFFFF'// ArkUI 解析为:AA=0xB8(72% 不透明), R=0xFF, G=0xFF, B=0xFF// 结果:带透明度的白色(正确!)3.3 Alpha 值换算表
| 不透明度 | 十六进制 AA 值 | 用途示例 |
|---|---|---|
| 100% | FF | 完全不透明 |
| 90% | E6 | CARD_B 卡片 |
| 80% | CC | 轻微透明 |
| 72% | B8 | CARD 毛玻璃卡片 |
| 50% | 80 | TEXT_2 副文字 |
| 30% | 4D | TEXT_3 占位文字 |
| 8% | 14 | LINE 分割线 |
| 0% | 00 | 完全透明 |
3.4 实际修复代码
// 修复前(错误):颜色格式错误,导致卡片变黄// static readonly CARD: string = '#FFFFFFB8' // 错误!// static readonly CARD_B: string = '#FFFFFFE6' // 错误!// 修复后(正确):#AARRGGBB 格式staticreadonlyCARD:string='#B8FFFFFF'// ✅ 72% 不透明白色staticreadonlyCARD_B:string='#E6FFFFFF'// ✅ 90% 不透明白色staticreadonlyLINE:string='#14141E14'// ✅ 8% 不透明深色(分割线)staticreadonlyTEXT_2:string='#14141E80'// ✅ 50% 不透明深色(副文字)记忆口诀:ArkUI 颜色格式 =A(透明度)在前,RGB 在后。与 CSS 的习惯正好相反!
四、AppFonts — 字体设计令牌
4.1 字体令牌定义
// AppFonts.etsexportclassAppFonts{// ── 字号(vp 单位)──────────────────────────staticreadonlySIZE_DISPLAY:number=28// 大标题(欢迎语)staticreadonlySIZE_TITLE:number=20// 页面标题staticreadonlySIZE_SECTION:number=16// 分区标题staticreadonlySIZE_BODY:number=14// 正文staticreadonlySIZE_META:number=11// 元数据/说明文字staticreadonlySIZE_MINI:number=10// 极小标签// ── 字重 ──────────────────────────────────staticreadonlyWEIGHT_BOLD:number=700// 粗体(标题)staticreadonlyWEIGHT_SEMIBOLD:number=600// 半粗(强调)staticreadonlyWEIGHT_MEDIUM:number=500// 中等(副标题)staticreadonlyWEIGHT_REGULAR:number=400// 常规(正文)}4.2 字体令牌对照表
| 令牌名 | 字号值 | 字重值 | 典型用途 |
|---|---|---|---|
| SIZE_DISPLAY | 28vp | BOLD (700) | 首页欢迎语、数字大标 |
| SIZE_TITLE | 20vp | BOLD (700) | 页面顶部标题 |
| SIZE_SECTION | 16vp | SEMIBOLD (600) | 列表分区标题 |
| SIZE_BODY | 14vp | MEDIUM (500) | 卡片主要文字 |
| SIZE_META | 11vp | REGULAR (400) | 时间戳、卡号掩码 |
| SIZE_MINI | 10vp | REGULAR (400) | 分类标签、徽标文字 |
4.3 在 UI 中使用字体令牌
import{AppFonts}from'../common/theme/AppFonts'import{AppColors}from'../common/theme/AppColors'// 卡号管理页 — 卡号数字显示Text('138****8888').fontSize(AppFonts.SIZE_SECTION)// 16vp.fontWeight(AppFonts.WEIGHT_BOLD)// 700.fontColor(AppColors.TEXT)// 应用列表行 — 应用名Text(appName).fontSize(AppFonts.SIZE_BODY)// 14vp.fontWeight(AppFonts.WEIGHT_MEDIUM)// 500.fontColor(AppColors.TEXT)// 说明文字Text('使用该号码注册的应用').fontSize(AppFonts.SIZE_META)// 11vp.fontColor(AppColors.TEXT_2)// 50% 透明度五、AppAnimations — 动画设计令牌
5.1 动画令牌定义
// AppAnimations.etsimport{curves}from'@kit.ArkUI'exportclassAppAnimations{// 标准过渡动画(按钮点击、状态切换)staticreadonlySTANDARD=curves.cubicBezierCurve(0.4,0,0.2,1)// 弹出动画(底部弹窗、卡片展开)staticreadonlySPRING=curves.springMotion(0.35,0.75)// 时长(毫秒)staticreadonlyDURATION_FAST:number=150// 快速切换(图标/颜色)staticreadonlyDURATION_NORMAL:number=300// 标准过渡staticreadonlyDURATION_SLOW:number=500// 复杂动画}5.2 在组件中使用动画令牌
import{AppAnimations}from'../common/theme/AppAnimations'// 按下效果.onClick(()=>{animateTo({duration:AppAnimations.DURATION_FAST,curve:AppAnimations.STANDARD},()=>{this.selectedIndex=newIndex})})// 弹出卡片动画(例如:添加卡号时的预览头像弹出).animation({duration:AppAnimations.DURATION_NORMAL,curve:AppAnimations.SPRING})六、设计令牌最佳实践
6.1 命名规范
- 语义化:用
TEXT_2(副文字)而不是GRAY_50(颜色本身) - 层级清晰:主色 → 变体(
PRIMARY→PRIMARY_2→PRIMARY_BG) - 功能分组:文字色、背景色、状态色、边框色分组命名
6.2 扩展方法
对于颜色枚举到 hex 的映射,使用独立方法而不是直接在令牌中硬编码:
// 在 AddAppPage.ets 中定义 CardColor → hex 的映射方法privatecardColorHex(c:CardColor):string{switch(c){case'blue':returnAppColors.PRIMARY// '#4F7CFF'case'purple':returnAppColors.PRIMARY_2// '#7C5CFF'case'green':return'#3CC463'case'orange':returnAppColors.WARN// '#FF7A1E'case'pink':returnAppColors.DANGER// '#FF2E4D'default:returnAppColors.PRIMARY}}6.3 避免魔法数字
// ❌ 魔法数字:14 是什么?为什么是 14?Text(appName).fontSize(14)// ✅ 使用令牌:一看就知道这是"正文"Text(appName).fontSize(AppFonts.SIZE_BODY)七、设计令牌与设计稿的对应关系
7.1 设计稿颜色变量映射
根据design/index.html设计稿,颜色变量与代码令牌的对应关系:
| 设计稿变量 | 代码令牌 | 十六进制值 |
|---|---|---|
--color-primary | AppColors.PRIMARY | #4F7CFF |
--color-text | AppColors.TEXT | #14141E |
--color-text-2 | AppColors.TEXT_2 | #14141E80 |
--card-bg | AppColors.CARD | #B8FFFFFF |
--card-bg-2 | AppColors.CARD_B | #E6FFFFFF |
--color-line | AppColors.LINE | #14141E14 |
7.2 字体规格对应
| 设计稿规格 | 代码令牌 | 典型应用 |
|---|---|---|
.card-num:15px Bold | SIZE_SECTION + WEIGHT_BOLD | 卡号管理页卡号数字 |
.body:14px Medium | SIZE_BODY + WEIGHT_MEDIUM | 应用列表 app 名 |
.meta:11px Regular | SIZE_META + WEIGHT_REGULAR | 运营商、时间戳 |
八、本篇小结
通过本篇,你掌握了号码助手设计令牌体系的全貌:
- 颜色令牌(AppColors):语义化命名,避免魔法颜色值散落全项目
- ArkUI 颜色格式:
#AARRGGBB(Alpha 在前!)这是开发者极易踩坑的地方 - 字体令牌(AppFonts):统一字号和字重,保证全应用排版一致性
- 动画令牌(AppAnimations):封装
cubicBezierCurve和springMotion,统一动画风格
最重要的记忆点:ArkUI 颜色是
#AARRGGBB,不是 CSS 的#RRGGBBAA!
下一篇将介绍应用配置详解:app.json5、module.json5和路由表main_pages.json的每个字段含义。
九、参考资料
本系列相关文章:
- 鸿蒙应用开发实战【02】— ArkTS 语法基础与工程结构解析
- 鸿蒙应用开发实战【14】— 毛玻璃卡片:#AARRGGBB 颜色格式深度解析
- 鸿蒙应用开发实战【24】— ArkUI 动画系统详解
官方文档:
- ArkUI 颜色参考
- Text 组件
- 动画概述
- curves API
如果这篇文章对你有帮助,欢迎点赞👍、收藏⭐、关注🔔,你的支持是我持续创作的动力!
相关资源:
- 开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net
- HarmonyOS 颜色文档:https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-appendix-enums
- curves 动画曲线:https://developer.huawei.com/consumer/cn/doc/harmonyos-references/js-apis-curve