news 2026/8/12 19:48:29

【细胞工坊|17】HarmonyOS ArkTS 视觉令牌实战:集中深色主题、间距和交互状态避免页面割裂

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【细胞工坊|17】HarmonyOS ArkTS 视觉令牌实战:集中深色主题、间距和交互状态避免页面割裂

本文基于「细胞工坊」真实 HarmonyOS ArkTS 源码编写,源码目录为D:\huawei\one14-9,重点复核entry/src/main/ets/common/Theme.etsConstants.etsIndex.ets以及首页、实验室、学习、我的等页面中的令牌调用。需要先说明一个边界:当前源码已经把深色视觉系统集中到AppColorsAppFontsConstants中,但没有实现亮色主题切换、资源限定目录、WithTheme或运行时setColorMode。因此本文讨论的是 HarmonyOS 5.0+ ArkUI 项目中“把深色主题令牌先收口”的工程方法,不会把源码没有实现的亮暗色动态切换写成已完成能力。

一、为什么先做视觉令牌,而不是直接谈亮暗色切换

HarmonyOS 应用做深浅色适配时,真正难的不是调用某个 API,而是先让页面不再各写各的颜色、字号、圆角和状态色。如果项目里每个页面都直接写#FFFFFF#1118271612,后续要改主题时就会出现三个问题:第一,无法确认哪个颜色是背景、哪个颜色是正文、哪个颜色只是临时装饰;第二,选中态、未选中态、提示态和危险态容易在不同页面表达不一致;第三,发布前做 AppGallery 色彩对比、深色模式、状态栏和导航栏检查时,需要跨页面逐个猜测意图。

「细胞工坊」的源码没有直接完成亮暗色双主题,但它已经做了一个更基础也更必要的工程动作:把视觉变量集中到了Theme.etsAppColors负责颜色语义,AppFonts负责字号和字重,Constants负责页面边距、卡片间距、圆角以及 Tab 索引。这个设计在真实项目里很关键,因为它把“页面长什么样”从页面实现中抽出来,变成可搜索、可审计、可替换的公共契约。

TAB_SELECTED为例,它不是一个孤立颜色,而是底部导航选中态的语义名称。页面不需要知道选中态究竟是绿色、蓝色还是品牌色,只需要消费AppColors.TAB_SELECTED。当后续要把深色主题扩展成亮色主题时,至少可以先定位到哪些地方依赖这个语义,再决定是否把它升级为资源引用、系统色或主题映射。

二、源码里的主题入口:Theme.ets 的职责划分

Theme.ets里有两个核心类:AppColorsAppFontsAppColors把颜色拆成几组:品牌主色、强调色、页面结构色、文字层级色、Tab 状态色和生物实验分类色。它没有把变量命名成BLUE_1GREEN_2这种纯视觉名称,而是用了PAGE_BGCARD_BGTEXT_PRIMARYTAB_UNSELECTEDCAT_DNA这类更接近业务和 UI 语义的名字。

export class AppColors { static readonly PAGE_BG: string = '#0B1120' static readonly CARD_BG: string = '#111827' static readonly DIVIDER: string = '#1F2937' static readonly TEXT_PRIMARY: string = '#E5F7FF' static readonly TEXT_SECONDARY: string = '#A7B6C8' static readonly TEXT_HINT: string = '#94A3B8' static readonly TAB_UNSELECTED: string = '#94A3B8' static readonly TAB_SELECTED: string = '#00FFB2' }

这种命名方式的价值在于,它能让开发者从调用点反推设计意图。比如PAGE_BG出现在页面根容器时,读者可以知道它是页面背景;CARD_BG出现在卡片区域时,可以知道它是信息容器背景;TEXT_SECONDARY出现在副标题和说明文字时,可以知道它是二级信息;ACCENT_RED出现在风险、错误、病毒类信息时,可以知道它承担提醒或危险含义。

AppFonts的职责更窄,当前集中定义了TITLE_SIZESUBTITLE_SIZEBODY_SIZECAPTION_SIZE以及WEIGHT_BOLDWEIGHT_MEDIUMWEIGHT_NORMAL。这不是复杂排版系统,但它足够支撑一个教育工具类应用的基础层级。标题、正文、说明、角标如果都从这里取值,页面之间不会因为临时写了 13、15、17 这类数字而变得割裂。

export class AppFonts { static readonly TITLE_SIZE: number = 20 static readonly SUBTITLE_SIZE: number = 16 static readonly BODY_SIZE: number = 14 static readonly CAPTION_SIZE: number = 12 static readonly WEIGHT_BOLD: FontWeight = FontWeight.Bold static readonly WEIGHT_MEDIUM: FontWeight = FontWeight.Medium static readonly WEIGHT_NORMAL: FontWeight = FontWeight.Normal }

这里也能看出源码的边界:它没有把颜色定义成 HarmonyOS 资源$r('app.color.xxx'),也没有提供 light/dark 两套资源文件。也就是说,它当前更像一个 ArkTS 层的深色主题 token 表,而不是完整的系统主题适配方案。这个边界需要在文章和发布材料里写清楚,否则就是夸大源码能力。

三、Constants.ets:把间距和圆角也纳入视觉契约

很多项目把“主题”只理解成颜色,但页面割裂往往来自间距和形状。一个页面卡片圆角 16,另一个页面圆角 20;一个页面左右边距 12,另一个页面左右边距 24;列表间距、底部导航高度、卡片内边距各自手写,最终会让用户感觉像在切换不同应用。

「细胞工坊」在Constants.ets中定义了PAGE_PADDINGCARD_GAPCARD_RADIUSSMALL_RADIUS,并定义了TAB_HOMETAB_LABTAB_LEARNTAB_MINE。前一组是视觉间距令牌,后一组是导航状态令牌。它们虽然不是颜色,但和视觉稳定性直接相关。

PAGE_PADDING = 16让页面内容有统一的呼吸空间;CARD_GAP = 12让卡片之间形成稳定节奏;CARD_RADIUS = 16SMALL_RADIUS = 12则把大卡片、小标签、按钮容器的圆角层级分开。对 HarmonyOS 多设备页面来说,这类令牌尤其重要。折叠屏、平板、2in1 小窗下,布局宽度会变化,但统一间距和圆角能减少页面在不同尺寸上的视觉漂移。

export class Constants { static readonly PAGE_PADDING: number = 16 static readonly CARD_GAP: number = 12 static readonly CARD_RADIUS: number = 16 static readonly SMALL_RADIUS: number = 12 static readonly TAB_HOME: number = 0 static readonly TAB_LAB: number = 1 static readonly TAB_LEARN: number = 2 static readonly TAB_MINE: number = 3 }

Tab 索引被放进Constants也有工程意义。底部导航如果用裸数字0123,页面读起来不直观,后续增加 Tab 或调整顺序时容易漏改。用Constants.TAB_HOME这类语义值,状态判断和页面渲染之间的关系更清楚。

四、Index.ets:底部导航如何消费 TAB_SELECTED

Index.ets是观察令牌是否真正落地的关键文件。页面的根容器背景使用AppColors.PAGE_BG,底部导航背景使用AppColors.CARD_BG,分割线使用AppColors.DIVIDER,Tab 图标和文字通过当前索引判断使用AppColors.TAB_SELECTEDAppColors.TAB_UNSELECTED。这说明令牌不是停留在公共文件里,而是进入了主导航状态机。

.fontColor(this.currentTab === index ? AppColors.TAB_SELECTED : AppColors.TAB_UNSELECTED)

底部导航的状态逻辑可以概括成一个小闭环:用户点击 Tab,currentTab更新;TabBarBuilder根据currentTab === index判断是否选中;选中态使用TAB_SELECTED,未选中态使用TAB_UNSELECTED;页面内容根据currentTab切换到首页、实验室、学习或我的。这里的颜色并不是装饰,而是状态反馈的一部分。

这类写法对 AppGallery 审核也有帮助。发布前检查底部导航时,至少可以快速确认选中态和未选中态来自同一组令牌,而不是某个页面自己写了一套颜色。如果未来审查发现绿色在深色背景上对比度不够,只需要优先检查TAB_SELECTED和底部导航背景,而不是在所有页面中搜索每个图标颜色。

Index.ets还使用了@StorageProp('statusBarHeight')@StorageProp('bottomBarHeight')处理顶部状态栏和底部安全区,这和视觉令牌配合起来,形成了两个层面的稳定性:颜色和状态由令牌控制,安全区由系统高度属性控制。对于 HarmonyOS 5.0+ 设备,这比单纯写固定 padding 更适合多设备和系统栏场景。

五、HomePage:主题令牌让首页信息层级更明确

首页通常最容易堆样式,因为它同时承担欢迎语、推荐内容、统计入口、快速操作和功能导览。「细胞工坊」的HomePage.ets中大量使用了AppColors.PAGE_BGAppColors.CARD_BGAppColors.TEXT_PRIMARYAppColors.TEXT_SECONDARYAppColors.TEXT_HINTAppFonts.TITLE_SIZEAppFonts.BODY_SIZE以及Constants.PAGE_PADDINGConstants.CARD_RADIUS

.backgroundColor(AppColors.PAGE_BG) .padding(Constants.PAGE_PADDING) .backgroundColor(AppColors.CARD_BG) .borderRadius(Constants.CARD_RADIUS)

这些调用让首页的信息层级有了可解释的规则。标题使用主文字和标题字号;说明使用二级文字或提示文字;卡片使用统一背景;页面外层使用统一深色背景;卡片圆角和页面边距来自统一常量。用户看到的不是某一段代码的样式堆砌,而是一套重复出现的视觉秩序。

首页仍然存在一些硬编码颜色,比如渐变背景、按钮或标签上的临时透明色。这些不是不能存在,但必须被看作后续主题适配的风险点。更稳妥的做法是把这些颜色继续拆成语义令牌,例如HERO_GRADIENT_STARTHERO_GRADIENT_ENDCHIP_BG_ACTIVECHIP_BORDER。这样在亮色主题或高对比模式下,开发者不会遗漏它们。

这也是本文刻意不把当前源码写成“已完成亮暗色适配”的原因。真实源码里已经有主题集中化基础,但仍有硬编码颜色没有完全收口。把这一点写清楚,比泛泛声称“支持深浅色模式”更有技术可信度。

六、LabPage:分类色要有业务语义,不能只靠好看

LabPage.ets负责实验相关页面,里面会出现生物实验分类、卡片列表、实验说明和状态入口。Theme.ets中的CAT_BASICCAT_CULTURECAT_DNACAT_VIRUS正好对应这类业务分类。与普通品牌色相比,分类色更容易被滥用,因为开发者可能只按“哪个颜色好看”来选择,而忽略颜色和内容类型之间的稳定关系。

把分类色放在AppColors里,至少带来两个好处。第一,分类颜色有了命名入口,后续可以在模型、页面和设计稿之间保持一致。第二,发布前可以统一检查分类色与文字、标签背景之间的对比度。尤其是CAT_DNA这类紫色、CAT_VIRUS这类红色,在深色背景上可能很醒目,但如果放到浅色背景、半透明卡片或小字号标签里,就需要重新验证。

LabPage中同样可以看到CARD_BGTEXT_PRIMARYTEXT_SECONDARYDIVIDER等令牌的使用。它说明主题系统不是只服务首页,而是在实验功能页继续复用。对一个合集文章来说,这一点很重要:文章不是抽象讨论设计规范,而是能回到源码中看到同一套令牌在多个页面上被消费。

仍需注意的是,页面里如果继续存在临时边框色、半透明背景色或渐变色,后续要么补充语义令牌,要么在发布前做单独检查。分类色只是主题系统的一部分,不能替代完整的前景/背景/边框/状态色体系。

七、LearningPage 与 MinePage:统一文字层级比统一颜色更容易被低估

学习页和我的页通常包含大量说明文字、入口卡片、统计数字和二级信息。用户在这些页面中不是只看颜色,而是在快速判断“什么最重要、什么可以稍后看、什么是状态说明”。如果字号和字重没有统一规则,即使颜色统一了,页面仍然会显得杂乱。

AppFonts.TITLE_SIZESUBTITLE_SIZEBODY_SIZECAPTION_SIZE在这里发挥作用。标题、模块名、正文说明、角标说明之间形成固定层级,开发者新增模块时不需要重新决定每个文本大小。对 ArkUI 页面来说,这也减少了Text()链式调用里的魔法数字,让 UI 树更可读。

从维护角度看,字体令牌还有一个现实价值:AppGallery 和多设备布局检查会关注文字是否过小、截断、遮挡、不可读。如果字号散落在页面里,很难系统检查。如果集中在AppFonts中,至少可以先判断基础字号是否符合手机、平板和 2in1 的可读性要求,再针对少量特殊场景做例外处理。

当然,当前源码里的AppFonts还比较轻量,没有定义行高、字间距、数字字体、标题层级 H1/H2/H3,也没有针对 PC 或平板单独给字号策略。这不是缺陷,而是项目阶段的边界。对一个教育类工具应用来说,先把常用字号和字重集中起来,已经能避免大量页面割裂问题。

八、从深色主题令牌走向完整亮暗色适配,需要补哪几层

如果后续要把「细胞工坊」从当前深色令牌系统升级为完整亮暗色适配,不能只把PAGE_BG改成白色。完整方案至少要补四层。

第一层是资源层。更符合 HarmonyOS 工程习惯的做法,是把关键颜色迁移为资源,例如app.color.page_bgapp.color.card_bgapp.color.text_primary,再通过不同资源目录或主题机制提供深色和亮色值。这样系统色彩模式变化时,页面可以通过资源解析获得不同结果,而不是在 ArkTS 类里硬判断。

第二层是语义层。当前AppColors已经有语义命名基础,但还需要把所有散落的硬编码颜色纳入语义命名。尤其是渐变、边框、半透明遮罩、按钮背景、标签背景、阴影和危险状态,不能只集中正文颜色。很多深浅色问题恰恰出现在这些“不重要”的颜色上。

第三层是组件层。页面不应该每次都从零组合卡片、标签、按钮和统计块。可以把高频组件抽成AppCardSectionHeaderCategoryChipStatTile,让组件内部消费令牌。这样主题变化时,组件级调整能覆盖更多页面。

第四层是验证层。深色和亮色都要检查正文对比度、按钮状态、禁用态、选中态、状态栏、导航栏、底部安全区、弹窗和长文本。尤其是TAB_SELECTED这类状态色,要在深色导航背景和可能的亮色导航背景上分别验证,不然选中态可能只在一种模式下清楚。

九、发布前如何审计视觉令牌是否真正可复核

写技术文章和做发布材料时,不能只说“使用主题令牌”。需要能被源码复核。对 05-17 这篇文章,我会按下面的方式审计。

第一,检查Theme.ets是否真实存在AppColorsAppFonts,并列出关键字段,例如PAGE_BGCARD_BGTEXT_PRIMARYTEXT_SECONDARYTAB_SELECTED。这些字段就是文章中的可复核证据。

第二,检查Constants.ets是否真实存在页面边距、卡片间距、圆角和 Tab 索引。文章中关于间距和导航状态的讨论必须能回到这些常量。

第三,检查Index.ets是否真实使用TAB_SELECTEDTAB_UNSELECTED。如果文章强调底部导航状态色,就必须能从主入口页面找到调用点。

第四,检查首页、实验室、学习和我的页面是否真实消费AppColorsAppFontsConstants。如果某个页面完全没有使用令牌,就不能把它写成主题系统的落地点。

第五,记录边界。当前源码没有实现完整亮色主题切换,因此文章标题和正文都要避免“已完成亮暗色适配”这种表述。更准确的说法是:源码完成了深色视觉令牌集中化,为后续亮暗色适配打基础。

十、工程落地建议:把硬编码颜色变成下一轮重构清单

对这类项目,我不建议一次性把所有页面重构成复杂设计系统。更务实的路径是先保留当前AppColorsAppFontsConstants,然后建立一张硬编码颜色清单。每发现一个页面内直接写颜色,就判断它属于哪种语义:页面背景、卡片背景、边框、正文、说明、提示、成功、危险、分类、选中、禁用、渐变或遮罩。

能归入现有令牌的直接替换,例如文本颜色、卡片背景和分割线。不能归入现有令牌的,新增语义字段,而不是用COLOR_1COLOR_2这种无意义名字。比如首页渐变可以拆成HOME_HERO_GRADIENT_STARTHOME_HERO_GRADIENT_END,分类标签可以拆成CATEGORY_CHIP_BGCATEGORY_CHIP_BORDER

同时,组件抽取要跟着真实重复走。页面里只出现一次的样式没必要马上抽组件;跨首页、实验室、学习页重复出现的卡片、标题行、统计块才值得抽。否则主题系统会过早变成一组难以理解的抽象,反而降低维护效率。

最后,任何主题重构都要配合截图和实际设备检查。视觉令牌不是为了让代码好看,而是为了让用户在不同页面、不同设备、不同系统栏环境中得到一致体验。对于 HarmonyOS 5.0+ 应用,这一点直接关系到多设备适配和 AppGallery 审核风险。

十一、本文对应的真实结论

基于D:\huawei\one14-9的源码,05-17 这篇文章能成立的真实结论是:细胞工坊已经把深色主题中的核心颜色、字体层级、页面间距、卡片圆角和底部导航状态集中到公共文件;Index.etsHomePage.etsLabPage.etsLearningPage.ets等页面实际消费了这些令牌;TAB_SELECTED是底部导航选中态的明确标记;当前源码仍有部分硬编码颜色,需要作为后续亮暗色适配和审核前视觉检查的风险点处理。

不能成立的结论是:源码已经支持完整亮色主题、系统深浅色自动切换、WithTheme局部主题覆盖或资源限定目录。文章不会把这些能力写成已实现。真正可靠的技术写作,应该把“已经做了什么”和“下一步可以怎么做”分开。对细胞工坊来说,当前已经完成的是视觉令牌收口;下一步才是把这些令牌迁移到更完整的 HarmonyOS 主题资源体系,并补齐亮色模式、组件化和对比度验证。

部分内容由AI辅助生成。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/12 19:47:10

Sunshine+Moonlight串流方案:局域网游戏串流与高清投屏实战指南

1. 项目概述:为什么选择SunshineMoonlight这套组合? 如果你和我一样,是个喜欢在客厅大电视上玩PC游戏,或者想把电脑桌面流畅地投射到安卓平板、电视盒子上进行办公、看片的人,那你肯定对“延迟”和“画质”这两个词深恶…

作者头像 李华
网站建设 2026/8/12 19:43:14

磁干扰测试实战:从原理到应用,解决G7手套对IMU传感器的干扰问题

最近在开发一款智能穿戴设备时,遇到了一个棘手的问题:设备内置的九轴IMU(惯性测量单元)传感器数据在特定环境下会突然出现剧烈跳变,导致姿态解算完全失效。经过层层排查,最终定位到干扰源——用户佩戴的含有…

作者头像 李华
网站建设 2026/8/12 19:38:59

WMS 仓储管理系统哪家的服务最好?从实施、售后到大促保障深度解析

引言很多企业在挑选 WMS 仓储管理系统时,习惯性优先对比功能清单、报价,却忽略一个核心真相:WMS 项目成败,三分看软件功能,七分看服务能力。市面上同类 WMS 产品在出入库、波次拣货、库存管理等基础功能趋同。但实施落…

作者头像 李华
网站建设 2026/8/12 19:32:55

Python动态数据爬取实战:从API请求到无头浏览器渲染

1. 项目概述:为什么动态数据爬取是爬虫工程师的必修课如果你用Python写过爬虫,大概率遇到过这种情况:用requests库配合BeautifulSoup,信心满满地写好了代码,结果运行后只抓回来一个空荡荡的HTML骨架,或者寥…

作者头像 李华
网站建设 2026/8/12 19:32:00

AI术语解析:从Agent到向量数据库,穿透技术黑话迷雾

1. 项目概述:当技术黑话成为沟通壁垒最近和几个不同领域的朋友聊天,发现一个挺有意思的现象:大家明明都在聊“AI”,但彼此说的话却像隔着一层毛玻璃,听得云里雾里。一个做市场的朋友兴奋地说他们部门在搞“AI Agent赋能…

作者头像 李华
网站建设 2026/8/12 19:31:59

深入解析PN结:从半导体基础到二极管特性与应用

1. 项目概述:从“半导体”到“PN结”的跨越 刚接触模拟电路,很多人会卡在第一个真正的“拦路虎”——PN结。翻开教材,满篇的“载流子”、“扩散运动”、“空间电荷区”,看得人云里雾里,感觉和之前学的电路基础完全是两…

作者头像 李华