鸿蒙应用开发实战【61】— 卡号颜色主题系统CardColor枚举映射
鸿蒙应用开发实战【61】— 卡号颜色主题系统CardColor枚举映射
本文是「号码助手全栈开发系列」第 61 篇,持续更新中…
开源社区:https://openharmonycrossplatform.csdn.net
前言
从第 28 篇开始,每个卡号都有一个color字段用于视觉标识。本篇系统梳理 CardColor 的设计——从类型定义到颜色值映射、从渐变双色到 UI 组件集成。这个设计看似简单,但它串联了数据模型、主题系统、颜色选择器和 AvatarBadge 等多个模块。
本篇涵盖:CardColor 联合类型定义、CARD_COLOR_HEX 颜色值映射表、cardGradient 渐变双色、CardDetailPage 颜色选择器、卡片颜色在 AvatarBadge 中的应用。
一、类型定义
1.1 联合字符串类型
exporttypeCardColor='blue'|'orange'|'green'|'pink'|'purple'为何选择 string literal union 而非 enum?
- ArkTS 对 TypeScript
enum编译支持有限,在特定版本中可能存在兼容问题 string联合类型与 RDB 存储天然兼容——color字段直接存'blue'字符串- 序列化/反序列化无需额外转换,减少了出错概率
1.2 在 Entity 中的使用
exportinterfaceCardEntity{id?:numberlabel:stringphone_number:stringcarrier:stringremark:string/** 显示颜色标识 */color:CardColor// 'blue' | 'orange' | 'green' | 'pink' | 'purple'sort_order:numbercreated_at:numberupdated_at:number}数据库创建时,color字段定义为TEXT NOT NULL DEFAULT 'blue'。
二、颜色值映射
2.1 CARD_COLOR_HEX 调色板
// AppColors.etsstaticreadonlyCARD_COLOR_HEX:string[]=['#4F7CFF',// blue — 品牌蓝'#3CC463',// green — 翡翠绿'#FF2E4D',// pink — 玫瑰红'#FF7A1E',// orange — 活力橙'#7B61FF'// purple — 梦幻紫]设计原则:
- 5 色满足用户辨识需求,不过多造成选择负担
- 颜色选中度高,涵盖冷暖色系
- 与主色
#4F7CFF(blue)一致,blue 作为默认值
2.2 cardGradient 渐变双色
每个卡号颜色对应一组渐变双色(用于AvatarBadge头像背景):
staticcardGradient(colorKey:string):[string,string]{switch(colorKey){case'blue':return[AppColors.PRIMARY,AppColors.PRIMARY_2]// #4F7CFF → #7C5CFFcase'green':return['#3CC463','#6BE28E']// 绿 → 浅绿case'pink':return['#FF2E4D','#FF7A90']// 红 → 浅红case'orange':return['#FF7A1E','#FFB067']// 橙 → 浅橙case'purple':return['#7B61FF','#9B85FF']// 紫 → 浅紫default:return[AppColors.PRIMARY,AppColors.PRIMARY_2]}}default 兜底:当数据库中存储了非法 color 值时,使用 blue 作为安全默认值。
三、UI 中的使用
3.1 AvatarBadge 头像
AvatarBadge({text:card.label,colorStart:AppColors.cardGradient(card.color)[0],colorEnd:AppColors.cardGradient(card.color)[1],badgeSize:64,radius:18,fontSize:18})CardDetailPage中展示卡号大头像时,利用cardGradient将'blue'这样的字符串映射为['#4F7CFF', '#7C5CFF'],形成渐变头像。
3.2 颜色选择器 Swatches
constCOLOR_KEYS:CardColor[]=['blue','green','pink','orange','purple']Row({space:10}){ForEach(COLOR_KEYS,(key:CardColor,index:number)=>{Stack(){if(this.selectedColorIndex===index){Text('✓').fontSize(Size.font12).fontWeight(800).fontColor('#FFFFFF')}}.width(Size.s30).height(Size.s30).borderRadius(Size.s9).backgroundColor(AppColors.CARD_COLOR_HEX[index])// 直接索引取色.border(this.selectedColorIndex===index?{width:2.5,color:'#FFFFFF',radius:9}:{width:0}).shadow(this.selectedColorIndex===index?{radius:10,color:AppColors.CARD_COLOR_HEX[index],offsetY:4}:{radius:0,color:'#00000000',offsetY:0}).onClick(()=>{this.selectedColorIndex=index})})}交互细节:
- 选中态:白色边框 + 外阴影 +
✓对勾 - 非选中态:无边框无阴影
CARD_COLOR_HEX[index]直接索引——COLOR_KEYS数组顺序与 hex 数组一一对应
3.3 保存时回写
// CardDetailPage.onSaveawaitCardDao.update({...card,color:COLOR_KEYS[this.selectedColorIndex],// CardColor 字符串值updated_at:now})selectedColorIndex映射回CardColor字符串,直接写入数据库。
四、完整设计回顾
┌──────────────────────────────────────────────────────────────┐ │ CardColor 系统全景图 │ ├──────────────────────────────────────────────────────────────┤ │ │ │ Models.ets AppColors.ets CardDetailPage │ │ ┌───────────┐ ┌─────────────┐ ┌─────────────┐ │ │ │ CardColor │───────▶│CARD_COLOR_ │───────▶│ 颜色选择器 │ │ │ │ = union │ │ HEX[5] │ │ swatches │ │ │ └───────────┘ ├─────────────┤ ├─────────────┤ │ │ ┌───────────┐ │cardGradient │───────▶│ AvatarBadge │ │ │ │CardEntity │ │( ) → [s,e] │ │ 渐变头像 │ │ │ │.color │ └─────────────┘ └─────────────┘ │ │ └───────────┘ │ │ │ │ │ ▼ │ │ RDB: cards.color = 'blue' / 'green' / 'pink' / ... │ │ (TEXT NOT NULL DEFAULT 'blue') │ │ │ └──────────────────────────────────────────────────────────────┘数据流:用户在颜色选择器选择 → index → CardColor 字符串 → RDB 存储 → 再次加载时通过cardGradient渲染
五、设计对比
5.1 CardColor 与枚举方案对比
| 维度 | 联合类型(当前方案) | TypeScript enum |
|---|---|---|
| ArkTS 兼容性 | ✅ 完全兼容 | ⚠️ 有限支持 |
| 数据库存储 | 直接存 ‘blue’,无需转换 | 需存数字或字符串值 |
| 序列化 | 天然兼容 JSON | 需额外转换逻辑 |
| 扩展性 | 类型 + hex + gradient 四步 | 自动序号,但需处理映射 |
| 编译时安全 | ✅ 类型检查严格 | ✅ 类型安全 |
5.2 扩展性考虑
如果需要增加新颜色:
// 1. 类型定义加一项exporttypeCardColor='blue'|'orange'|'green'|'pink'|'purple'|'teal'// 2. 颜色常量加 hexstaticreadonlyCARD_COLOR_HEX:string[]=[...,'#00BFA5']// 3. cardGradient 加新 casecase'teal':return['#00BFA5','#64FFDA']// 4. COLOR_KEYS 数组加一项constCOLOR_KEYS:CardColor[]=['blue','green','pink','orange','purple','teal']四步即可无缝扩展,体现了解耦设计的优势。
小结
| 要点 | 说明 |
|---|---|
| 类型定义 | type CardColor = 'blue' | 'orange' | ...联合类型 |
| 颜色映射 | CARD_COLOR_HEX[5] 对应 5 色调色板 |
| 渐变双色 | cardGradient(key) → [start, end] 渐变对 |
| 颜色选择器 | 索引匹配,选中态白边 + 阴影 + ✓ |
| 存储 | RDB TEXT 字符串,default blue |
| 扩展 | 类型 + hex + gradient + 数组 四步新增颜色 |
如果这篇文章对你有帮助,欢迎点赞👍、收藏⭐、关注🔔,你的支持是我持续创作的动力!
相关资源:
- openHarmony 跨平台社区:https://openharmonycrossplatform.csdn.net
- HarmonyOS 官方文档:https://developer.huawei.com/consumer/cn/doc/
- HarmonyOS 颜色资源开发指南:https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/resource-categories-and-access
- HarmonyOS 主题换肤开发:https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/theme-switch