资讯动态

HarmonyOS7 颜色 Token 让主题更稳:ArkUI/ArkTS 实战拆解

发布时间:2026/8/12 20:05:56 来源:尧图企业网站定制
文章目录前言为什么这个问题经常被写乱场景品牌页接入深色模式常用颜色语义实操步骤先把页面目标想清楚完整示例语义颜色驱动品牌页把关键代码一段段拆开容易踩坑的点优化建议颜色 Token 要先分清语义写在最后前言颜色 token 的重点不是把色值藏起来而是让颜色具备语义。品牌色、危险色、辅助文字、页面背景这些角色稳定了主题切换才不会牵一发动全身。这篇单独聊品牌页这个场景。重点不是堆 API而是把品牌色、危险色、辅助文字和背景色按语义收口避免主题切换时到处改组件。为什么这个问题经常被写乱颜色 Token 让主题更稳 这类内容很容易被写成“代码能跑就算讲完了”但对初学者来说这恰恰是最不够的地方。真正让人卡住的往往不是某个组件名记不住而是不知道这段代码为什么要这样拆、状态为什么要这样放、以后需求变化时应该从哪里改。所以这篇文章不只想给你一个能跑的例子更想把背后的判断过程讲清楚。你只要把这个判断过程吃透后面自己改页面、补需求、查问题时心里会稳很多。场景品牌页接入深色模式颜色 token 最容易在项目中后期暴露价值。早期页面少按钮直接写#0A59F7危险操作直接写#D92D20看起来没什么问题。等品牌升级、深色模式上线、营销页要换主题时散落在页面里的色值就会变成维护成本。品牌页尤其明显主按钮、选中态、活动标签、说明文字、分割线、卡片背景都和颜色有关。如果每个组件都直接绑定一个具体色值主题切换时就要到处改。语义 token 的做法是让组件只关心“这是品牌色”“这是危险色”“这是弱文本”不关心它今天具体是哪个蓝。颜色 token 的价值不是少写几个色值而是让主题变更不会扩散到每个组件。常用颜色语义Token浅色值深色值用途colorBrand#0A59F7#6EA8FF主按钮、选中态colorDanger#D92D20#FF8A80删除、异常colorSuccess#0A7F3F#62D28F成功、完成colorTextPrimary#111111#F2F4F8主文案colorTextSecondary#666666#B8C0CC辅助说明colorPageBg#F5F7FA#111318页面背景colorCardBg#FFFFFF#1C2028卡片背景实操步骤先按语义列出页面用色不要按色相列blue1、red2。页面组件只引用 token 方法不直接散写色值。深浅主题切换时只改变 token 返回值不改页面结构。危险、成功、品牌三个语义要分开不能拿品牌色硬顶所有状态。检查卡片背景和页面背景的层级暗色模式下尤其容易糊成一片。先把页面目标想清楚在真正写代码之前先别急着盯着 API。更有用的做法是先想清楚这个页面到底想解决什么问题用户最在意的反馈是什么哪些状态必须一直保持一致。当你先把这条主线想明白再回头看组件和状态设计很多选择都会顺理成章。对小白来说这一步尤其重要因为它能帮你从“照着抄”慢慢过渡到“看得懂、改得动”。完整示例语义颜色驱动品牌页EntryComponentstruct ColorTokenPage{StatedarkMode:booleanfalseStateselectedPlan:stringproprivatebrand():string{returnthis.darkMode?#6EA8FF:#0A59F7}privatedanger():string{returnthis.darkMode?#FF8A80:#D92D20}privatesuccess():string{returnthis.darkMode?#62D28F:#0A7F3F}privatetextPrimary():string{returnthis.darkMode?#F2F4F8:#111111}privatetextSecondary():string{returnthis.darkMode?#B8C0CC:#666666}privatepageBg():string{returnthis.darkMode?#111318:#F5F7FA}privatecardBg():string{returnthis.darkMode?#1C2028:#FFFFFF}BuilderPlanCard(name:string,price:string,plan:string){Column({space:8}){Row(){Text(name).fontSize(18).fontWeight(FontWeight.Bold).fontColor(this.textPrimary())Blank()Text(this.selectedPlanplan?已选:可选).fontSize(12).fontColor(this.selectedPlanplan?this.success():this.textSecondary())}.width(100%)Text(price).fontSize(24).fontWeight(FontWeight.Bold).fontColor(this.brand())Text(颜色来自语义 token主题变化时组件不用改。).fontSize(13).fontColor(this.textSecondary())Button(this.selectedPlanplan?当前方案:选择方案).enabled(this.selectedPlan!plan).backgroundColor(this.brand()).onClick(()this.selectedPlanplan)}.alignItems(HorizontalAlign.Start).padding(14).backgroundColor(this.cardBg()).borderRadius(8)}build(){Column({space:14}){Row(){Text(主题预览).fontSize(22).fontWeight(FontWeight.Bold).fontColor(this.textPrimary())Blank()Toggle({type:ToggleType.Switch,isOn:this.darkMode}).onChange((value:boolean)this.darkModevalue)}.width(100%)this.PlanCard(专业版,¥129/月,pro)this.PlanCard(团队版,¥399/月,team)Button(删除试用数据).width(100%).backgroundColor(this.danger())}.padding(16).height(100%).backgroundColor(this.pageBg())}}把关键代码一段段拆开brand()、danger()、success()是语义入口。组件不需要知道浅色模式品牌色是哪个蓝也不需要知道深色模式危险色该提亮多少只要知道当前用途是品牌、危险还是成功。pageBg()和cardBg()分开很重要。暗色模式下如果页面和卡片都用同一个深色卡片层级会消失用户很难扫读内容。PlanCard()里没有散写业务色值只有 token 调用。真实项目可以把这些方法迁到主题对象或资源文件页面代码基本不用动。容易踩坑的点用blue1、blue2命名品牌色一换名字就失效。危险按钮复用品牌色只靠文案表达删除风险。暗色模式只反转背景没有调整辅助文字对比度。卡片背景和页面背景太接近层级不清楚。同一个语义在不同页面写了不同色值主题升级时漏改。优化建议颜色 token 不要一次性设计几十个。先从品牌、危险、成功、主文案、弱文案、页面背景、卡片背景开始覆盖大多数页面后再补充分割线、遮罩、禁用态等细项。深色模式不是简单把背景变黑。危险色、成功色、品牌色都要考虑可读性尤其是小字号标签和弱提示文案。上线前建议在真实设备上看一遍亮度较低的场景很多对比度问题在模拟器里不明显。颜色 Token 要先分清语义颜色 token 的重点不是少写几个#而是让每个颜色有稳定角色。品牌色、危险色、成功色、主文案、辅助文案、页面背景和卡片背景这些语义一旦稳定主题切换就不会扩散到每个组件。示例里的brand()、danger()、success()分别承担不同含义。删除按钮不能因为品牌色好看就继续用品牌色成功提示也不应该和危险提示只靠文案区分。颜色语义越清楚用户越容易理解状态。写在最后暗色模式尤其要注意层级。页面背景和卡片背景如果太接近内容会糊成一片辅助文字如果过暗低亮度设备上会很难读。主题适配不是简单换一组色值而是要保证信息层级仍然成立。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价