news 2026/10/22 12:45:09

【化学实验室|17】HarmonyOS ArkTS 亮暗色与视觉令牌实战:集中颜色、间距和交互状态避免页面割裂

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【化学实验室|17】HarmonyOS ArkTS 亮暗色与视觉令牌实战:集中颜色、间距和交互状态避免页面割裂

一个项目拥有Theme.ets,不等于它已经拥有完整主题系统。真正可维护的主题,需要回答四个问题:颜色表达的是业务语义还是某个十六进制值;浅色与深色是否使用同一组资源名称;系统状态栏、普通 ArkUI 组件和 Canvas 是否能同步变化;选中、按下、禁用和错误状态是否都经过对比度验证。

本文基于化学实验室 1.0.5的真实 HarmonyOS ArkTS 工程展开。源码中已经有AppColors与AppFonts,Constants.ets也集中保存了页面间距、卡片间距和圆角。然而,EntryAbility.ets在创建阶段强制设置COLOR_MODE_LIGHT;base/element/color.json定义了多种颜色,dark/element/color.json却只有启动窗口背景;部分页面、弹窗、Canvas 和系统栏仍直接写入#F0F0F0、#FFFFFF、#CCCCCC等色值。

这不是简单的“把白色改成黑色”问题。直接替换可能造成正文变暗、图表坐标线消失、未选中标签与卡片背景混在一起,甚至状态栏图标和背景使用同一明暗方向。正确做法是先建立语义令牌契约,再让资源限定词自动提供浅色和深色值。

主题系统的核心不是集中保存十六进制颜色,而是让页面、组件、系统栏和绘制层共同消费稳定的语义资源。

CHEM-LAB-ONE12-SEMANTIC-THEME-TOKENS-20260730

本文将完成以下工作:

  • 核对工程当前颜色模式、主题常量和资源目录。
  • 区分颜色常量、语义令牌与资源限定词的职责。
  • 盘点AppColors已覆盖的区域和仍然散落的硬编码颜色。
  • 设计 base 与 dark 使用相同名称的颜色资源。
  • 让 ArkUI 页面从字符串色值迁移到$r('app.color.xxx')。
  • 统一间距、圆角、字号与交互状态。
  • 处理状态栏、导航栏、弹窗、阴影和 Canvas 的主题同步。
  • 给出分阶段迁移、构建检查、对比度计算与双模式回归表。

一、先确认工程当前不是“跟随系统”

EntryAbility.ets的onCreate()中存在以下真实代码:

this.context.getApplicationContext().setColorMode( ConfigurationConstant.ColorMode.COLOR_MODE_LIGHT )

这行代码把应用锁在浅色模式。它解释了为什么当前页面即使在系统开启深色模式时仍保持浅色,也解释了为什么dark/element/color.json长期没有被补齐:运行时通常不会进入深色资源匹配。

因此本文的第一条结论是:在迁移完成前,锁定浅色可以避免半成品主题进入用户界面;在 base、dark、系统栏和绘制层全部验证后,才删除这条强制浅色设置,让应用重新跟随系统。不能先解除锁定,再边运行边寻找白底白字问题。

二、Theme.ets 已经提供了一个起点

当前Theme.ets把颜色分成品牌、状态、背景、文字、Tab 和实验分类几组:

export class AppColors { static readonly PRIMARY: string = '#0052D9' static readonly PRIMARY_BG: string = '#E8F1FF' static readonly PAGE_BG: string = '#F5F7FA' static readonly CARD_BG: string = '#FFFFFF' static readonly DIVIDER: string = '#EEEEEE' static readonly TEXT_PRIMARY: string = '#1A1A1A' static readonly TEXT_SECONDARY: string = '#475467' static readonly TEXT_HINT: string = '#6B7280' }

HomePage.ets、LearningPage.ets、LabPage.ets、MinePage.ets、ExperimentCard.ets、DataTable.ets等文件都在消费这些值。集中常量已经减少了主页面之间的随机色差,也使品牌蓝和正文色可以统一修改。

但static readonly string只是在代码层共享字符串。它不会根据资源限定词自动变化,也不能让系统在颜色模式切换时重新匹配资源。这个结构适合迁移前盘点,不适合作为最终的双模式资源层。

三、资源文件与代码常量目前存在两套真源

工程的base/element/color.json中已经存在primary_blue、page_background、card_background、text_primary等资源,但它们与Theme.ets的值并不完全一致。例如资源文件中的主色是#2979FF,Theme.ets中的主色是#0052D9;资源里的辅助绿色是#00C853,代码常量中则是#087443。

当同一个语义有两套值时,会出现三个后果:

  1. 使用$r()的启动页和使用AppColors的业务页看起来不是同一套品牌。
  2. 修改Theme.ets无法覆盖资源引用,修改color.json也无法覆盖字符串常量。
  3. 深色资源只能替换$r()引用,无法替换编译进代码的字符串。

迁移时必须指定唯一真源。对需要根据配置自动变化的颜色、尺寸和媒体,优先使用资源系统;Theme.ets可以保留类型、状态映射和非视觉常量,但不再保存两套重复色值。

四、dark 目录只有一个资源意味着什么

当前dark/element/color.json只有:

{ "color": [ { "name": "start_window_background", "value": "#FFFFFF" } ] }

它不仅没有覆盖页面、卡片和文字颜色,连启动背景仍是白色。若解除浅色锁定,系统能匹配到的深色资源极少,大多数业务组件继续使用浅色色值。这会形成“系统进入深色、应用局部仍为浅色”的割裂状态。

HarmonyOS 资源系统支持颜色模式限定词。base提供默认值,dark目录提供同名覆盖值;组件仍引用同一个资源名称,运行时根据当前配置匹配。重点是同名、同语义、不同取值,而不是给深色版本再创建一套dark_text_primary名称。

五、先设计语义名称,再选择色值

不建议直接把现有变量机械转换为blue_500、gray_900。页面真正关心的是用途:这是页面背景、卡片背景、正文、弱提示、边界、主操作还是危险状态。推荐最小语义集合如下:

语义资源浅色职责深色职责
surface_page页面底色深色页面底色
surface_card卡片与弹窗抬高的深色表面
surface_muted输入框、未选标签次级深色表面
content_primary标题与正文高强调文字
content_secondary说明文字中强调文字
content_hint占位与弱提示低强调文字
border_subtle分割线与边框可见但克制的边界
action_primary主按钮与选中态深色环境下主操作
action_on_primary主按钮上的文字主操作上的文字
status_success成功与安全成功与安全
status_warning警告与注意警告与注意
status_danger错误与危险错误与危险

命名不带具体颜色,未来品牌蓝调整、对比度修复或高对比主题增加时,业务组件都无需改名。

六、建立 base 与 dark 的同名资源

浅色资源可以先从当前Theme.ets的稳定值迁移:

{ "color": [ { "name": "surface_page", "value": "#F5F7FA" }, { "name": "surface_card", "value": "#FFFFFF" }, { "name": "surface_muted", "value": "#F0F0F0" }, { "name": "content_primary", "value": "#1A1A1A" }, { "name": "content_secondary", "value": "#475467" }, { "name": "content_hint", "value": "#6B7280" }, { "name": "border_subtle", "value": "#E5E7EB" }, { "name": "action_primary", "value": "#0052D9" }, { "name": "action_on_primary", "value": "#FFFFFF" }, { "name": "status_success", "value": "#087443" }, { "name": "status_warning", "value": "#B45309" }, { "name": "status_danger", "value": "#B42318" } ] }

dark/element/color.json使用完全相同的名称,但选择经过对比度验证的深色值:

{ "color": [ { "name": "surface_page", "value": "#111418" }, { "name": "surface_card", "value": "#1B2026" }, { "name": "surface_muted", "value": "#252B33" }, { "name": "content_primary", "value": "#F5F7FA" }, { "name": "content_secondary", "value": "#C4CBD4" }, { "name": "content_hint", "value": "#9AA4B2" }, { "name": "border_subtle", "value": "#353D47" }, { "name": "action_primary", "value": "#6EA8FF" }, { "name": "action_on_primary", "value": "#0B1F3A" }, { "name": "status_success", "value": "#5BD6A2" }, { "name": "status_warning", "value": "#F4B95E" }, { "name": "status_danger", "value": "#FF8C82" } ] }

这些值是迁移起点,不是所有项目通用的固定答案。最终仍要用真实字体、字号、透明度和背景组合计算对比度,并在设备上观察视觉层级。

七、组件只引用语义资源

原代码:

Text('实验室') .fontColor(AppColors.TEXT_PRIMARY) Column() .backgroundColor(AppColors.CARD_BG)

迁移后:

Text('实验室') .fontColor($r('app.color.content_primary')) Column() .backgroundColor($r('app.color.surface_card'))

组件不需要读取isDark,也不需要写三元表达式。资源匹配层负责提供颜色,组件只表达“这里是主文字”“这里是卡片表面”。这样系统主题变化时,页面结构不会出现大量条件分支。

八、Theme.ets 应从颜色仓库变成主题契约

迁移完成后,Theme.ets不必被删除。它可以保存语义角色、组件状态映射或纯类型,避免业务页面拼接资源名:

export interface ComponentTone { background: ResourceColor foreground: ResourceColor border: ResourceColor } export enum VisualState { Normal, Selected, Disabled, Danger }

如果团队希望集中导出资源引用,也要确保导出的仍是ResourceColor,不是十六进制字符串。最重要的边界是:主题契约描述角色,资源文件提供配置相关的值,业务组件消费角色。

九、间距和圆角也属于视觉令牌

Constants.ets已经集中保存:

static readonly PAGE_PADDING: number = 16 static readonly CARD_GAP: number = 12 static readonly CARD_RADIUS: number = 16 static readonly SMALL_RADIUS: number = 12

这是正确方向,但命名仍偏“某个数值放在哪里”。随着平板、2in1 和自由窗口加入,同一语义可能需要不同密度。例如紧凑窗口页面边距 16vp,宽屏内容区边距 24vp;普通卡片圆角 12vp,弹窗圆角 20vp。

可以把数值升级为尺度:space_xs、space_s、space_m、space_l,再由组件规则决定使用哪一档。若尺寸需要随设备或配置匹配,也可以放入 float 资源,通过$r('app.float.space_m')引用。这样页面不会同时出现 15、16、18 三个几乎相同的边距。

十、字号令牌不能替代动态字体测试

当前AppFonts提供 20、16、14、12 四档字号和三档字重。集中字号能维持层级,但不能证明固定高度容器支持系统字体放大。HomePage的 Banner、列表行、按钮和 Tab 都需要在较大字体下验证。

建议用语义名表达用途:title_page、title_section、body、caption,并遵循以下规则:

  • 普通正文优先允许换行,而不是缩小到不可读。
  • 按钮文字设置合理maxLines,容器高度保留弹性。
  • 卡片标题与说明使用不同语义字号,不用单一字号加粗模拟所有层级。
  • Canvas 内文字也要从同一套字号与颜色规则读取,不能独立写死。

十一、硬编码颜色需要分类迁移

源码扫描可看到多类硬编码:

CategoryTabs.ets #F0F0F0 SearchBar.ets #F0F0F0 DataTable.ets #F5F5F5 / #CCCCCC ChartView.ets #FFFFFF / #EEEEEE EntryAbility.ets #F5F7FA / #1A1A1A / #FFFFFF LearningPage.ets #1A237E / #3949AB

不能用一次全局替换处理,因为它们职责不同:#F0F0F0可能是未选标签、搜索框或数据表头;#FFFFFF可能是卡片、按钮文字或 Canvas 背景;渐变色可能是品牌 Banner,而不是普通表面。

正确顺序是先给每处硬编码标注语义,再替换为对应资源。无法判断用途的颜色应保留到组件审查阶段,不能因为颜色相同就认定语义相同。

十二、交互状态需要独立令牌

当前分类标签通常只区分 selected 和 normal:

.fontColor(selected ? AppColors.TEXT_WHITE : AppColors.TEXT_SECONDARY) .backgroundColor(selected ? AppColors.PRIMARY : '#F0F0F0')

真实交互还包括 pressed、focused、disabled 与 error。建议为组件建立状态表:

状态背景文字边框验收重点
normalsurface_mutedcontent_secondary透明标签可辨识
selectedaction_primaryaction_on_primary主色选中明显
pressed主色压暗或叠层高对比文字主色有即时反馈
focused原背景原文字焦点色键盘可定位
disabled禁用表面禁用文字弱边界不像可点击
error危险弱背景危险文字危险色不只依赖红色

状态不能只靠色相区分。错误状态还应有文字或图标,焦点状态要有轮廓,禁用状态要同时停止点击行为。

十三、系统栏必须和页面主题同步

EntryAbility.ets当前把系统栏固定为浅色:

mainWindow.setWindowSystemBarProperties({ statusBarColor: '#F5F7FA', statusBarContentColor: '#1A1A1A', isStatusBarLightIcon: false, navigationBarColor: '#FFFFFF', navigationBarContentColor: '#1A1A1A', isNavigationBarLightIcon: false })

解除浅色锁定后,如果这里不变,深色页面顶部仍会出现浅色条。应把系统栏配置封装成一个窗口级方法,在窗口创建和颜色配置变化时调用。方法输入是当前主题画像,输出是背景色、内容色以及图标明暗方向。

interface SystemBarPalette { statusBackground: string statusContent: string navigationBackground: string navigationContent: string useLightIcon: boolean }

系统栏属于窗口层,不应散落在每个业务页面。验证时要同时观察普通页面、弹窗、返回后的页面和冷启动窗口,避免只修主页面截图。

十四、Canvas 不会自动理解组件主题

ChartView.ets使用 Canvas 绘制背景、网格、文字和折线,其中既有AppColors,也有#FFFFFF、#CCCCCC、#EEEEEE。ArkUI 的Text可以直接消费资源颜色,但 Canvas 上下文最终需要明确的绘制色值,而且主题变化后还要重新绘制。

可以把图表调色板作为输入:

interface ChartPalette { background: string axis: string grid: string label: string line: string point: string } private drawChart(palette: ChartPalette): void { this.ctx.fillStyle = palette.background this.ctx.strokeStyle = palette.grid // 绘制网格、标签、折线和数据点 }

窗口或主题层解析当前资源后生成ChartPalette,Canvas 组件在调色板变化时清屏并重绘。只修改页面背景而不重绘 Canvas,会留下白色绘图区或不可见坐标线。

十五、实验模拟 Canvas 要区分物体色与界面色

ExperimentSimPage.ets中存在大量烧杯、液体、导线、刻度和背景色。它们不能全部迁移成页面主题色。应拆成两类:

  • 界面色:画布背景、说明文字、网格、控制面板、边框,随主题变化。
  • 内容色:化学液体、火焰、金属、指示剂、实验器材,用于表达实验对象,通常保持稳定。

如果把指示剂红色替换成深色主题的危险色,实验含义就会被破坏;如果让画布背景始终白色,深色页面又会出现刺眼亮块。因此 Canvas 迁移必须按语义,而不是按色值数量批量替换。

十六、阴影在深色模式下不能照搬

源码多处使用半透明黑色阴影:

.shadow({ radius: 2, color: '#08000000', offsetY: 1 })

在浅色背景中,轻微黑影能表达卡片层级;在深色背景中,同样阴影几乎不可见。深色层级更适合使用表面亮度差、细边框或更克制的环境光效果。建议把卡片层级拆成surface_page、surface_card、border_subtle,阴影仅作为增强,而不是唯一边界。

回归时关闭阴影观察卡片是否仍可识别。如果完全依赖阴影,说明背景与卡片表面缺少足够层级差。

十七、渐变与品牌色要验证文字对比度

HomePage和LearningPage使用蓝色渐变 Banner,文字通常是白色。深色模式不一定需要把品牌渐变反转,但要检查渐变最亮区域与白字的对比度,尤其是小字号说明和透明图标。

建议把 Banner 定义成一组配对令牌,而不是单个背景色:

interface BannerTone { start: ResourceColor end: ResourceColor title: ResourceColor description: ResourceColor buttonBackground: ResourceColor buttonText: ResourceColor }

这样修改渐变时会同时审查其上的标题、说明和按钮,不会只调整背景后留下不可读文字。

十八、计算对比度而不是凭肉眼判断

对比度需要按前景与背景的相对亮度计算。以下 TypeScript 工具可用于开发期校验十六进制颜色:

function channel(value: number): number { const s = value / 255 return s <= 0.03928 ? s / 12.92 : Math.pow((s + 0.055) / 1.055, 2.4) } function luminance(hex: string): number { const value = hex.replace('#', '') const r = parseInt(value.slice(0, 2), 16) const g = parseInt(value.slice(2, 4), 16) const b = parseInt(value.slice(4, 6), 16) return 0.2126 * channel(r) + 0.7152 * channel(g) + 0.0722 * channel(b) } function contrast(foreground: string, background: string): number { const a = luminance(foreground) const b = luminance(background) const light = Math.max(a, b) const dark = Math.min(a, b) return (light + 0.05) / (dark + 0.05) }

工程发布检查可把正文与背景目标设为不低于 4.5:1,关键图标、标题和按钮等至少检查 3:1。透明色需要先与实际背景合成,再计算最终颜色,不能直接拿八位十六进制的 RGB 部分计算。

十九、迁移要按可回滚批次进行

一次改完几十个页面风险很高。建议分六批:

  1. 建立 base/dark 同名资源,不解除浅色锁定。
  2. 迁移Index、首页、实验室、学习和“我的”五个主页面。
  3. 迁移共用卡片、搜索、分类标签、表格与弹窗。
  4. 迁移二级页面和交互状态,清理普通 UI 硬编码色。
  5. 处理系统栏、ChartView 与实验模拟 Canvas。
  6. 补齐深色启动资源,解除浅色锁定并执行完整回归。

每批结束都运行构建和核心页面检查。若发现颜色问题,可以回滚单个批次,不会在整个工程中追查一次性替换造成的连锁错误。

二十、用脚本持续发现新增硬编码

迁移完成后,仍需要阻止新代码重新引入散落色值。开发期可以执行:

rg -n --glob '*.ets' "#[0-9A-Fa-f]{6,8}" entry/src/main/ets

白名单可以保留实验内容色、需要固定的品牌素材或确有依据的 Canvas 物体色;普通页面背景、文字、边框、按钮和状态色不应继续新增。审查记录要写明文件、行号、语义和保留原因。

资源层也需要检查同名覆盖。一个简单的校验脚本可以读取 base 与 dark 的color.json,比较资源名称集合:

const missingInDark = baseNames.filter((name) => !darkNames.includes(name)) if (missingInDark.length > 0) { throw new Error(`dark resources missing: ${missingInDark.join(', ')}`) }

这样新增浅色语义资源却忘记补深色值时,构建或检查阶段就能发现。

二十一、构建验证不能省略

资源名迁移最容易产生拼写错误、资源类型错误和漏文件。工程根目录使用项目既有 hvigor 命令构建:

$env:DEVECO_SDK_HOME='D:\huawei\DevEco Studio\sdk' $env:PATH='D:\huawei\DevEco Studio\jbr\bin;' + $env:PATH & 'D:\huawei\DevEco Studio\tools\hvigor\bin\hvigorw.bat' --no-daemon assembleHap

构建通过只说明资源可解析、ArkTS 可编译,不说明视觉正确。仍要在浅色、深色、冷启动、前后台切换、横竖屏和自由窗口下走完整页面。

二十二、主页面双模式验收表

页面场景预期结果通过标准
首页浅色启动页面与卡片层级清楚正文可读,Banner 按钮清晰
首页切到深色页面、卡片、标签同步无突兀白块,未选标签可辨
实验室分类切换selected/normal 明确两种模式都能识别当前分类
学习渐变 Banner白字与按钮可读最亮区域仍保持清晰
我的卡片与分割线层级稳定分割线不消失也不过亮
Tabs选中与未选中状态区别明确颜色外仍有位置或图标反馈

测试时先进入页面,再切换系统颜色模式,并返回上一级。若只有重新启动后才更新,说明页面或绘制层缓存了旧主题值。

二十三、组件与绘制层验收表

对象操作预期结果失败信号
SearchBar输入、清空、失焦输入区与占位符可辨背景和卡片融为一体
CategoryTabs点击、按压、键盘焦点四类状态可区分只在浅色可见焦点
DataTable查看表头、行、分割线数据行扫描顺畅深色中网格消失
NoteEditorDialog打开、编辑、关闭浮层高于页面且文字清晰弹窗仍是纯白或输入框发黑
ChartView切换主题背景、轴、标签、折线重绘留下旧主题画布
ExperimentSim运行实验器材含义不变、界面适配内容色被误替换成主题色

通过标准必须包含操作结果,不只记录“截图看起来正常”。例如 ChartView 需要在主题切换后重新绘制,分类标签需要能继续点击,弹窗关闭后背景恢复正确。

二十四、系统级场景验收表

场景操作步骤预期结果
冷启动深色系统下杀进程后启动启动背景、状态栏、首屏连续,无白色闪屏
热切换应用前台切换系统主题当前页与系统栏同步更新
前后台切后台改主题再返回页面不保留旧主题缓存
横竖屏两种主题下旋转无固定背景条与文字裁切
平板分屏缩放窗口后切主题响应式布局与颜色同时正确
2in1鼠标悬停与键盘焦点深浅色都能看见反馈轮廓
字体放大较大系统字体下切主题文字不被固定高度遮挡

二十五、常见失败与定位方式

页面切换后局部恢复浅色

检查二级页面是否仍引用AppColors字符串或硬编码色;同时检查页面是否缓存了主题解析结果。优先搜索#色值和AppColors使用点。

深色模式出现白色启动闪屏

检查dark/element/color.json中的start_window_background,并核对启动图、应用图标背景和首屏页面背景是否连续。

状态栏图标看不清

检查系统栏背景、内容色和isStatusBarLightIcon是否成套更新。不能只改背景,不改图标明暗方向。

Canvas 仍显示旧颜色

检查主题变化后是否调用清屏和重绘;确认调色板是新对象或可观察状态,避免仅修改普通 ArkUI 背景。

深色卡片没有边界

检查surface_page与surface_card的亮度差、border_subtle和阴影策略。不要只增加更重黑影。

二十六、源码级完成清单

  • EntryAbility.ets不再永久强制浅色,且系统栏可跟随主题。
  • base 与 dark 对所有语义资源使用相同名称。
  • Theme.ets不再与color.json维护重复色值。
  • 五个主页面的背景、文字、边界和状态均使用语义资源。
  • SearchBar、CategoryTabs、DataTable、弹窗等共用组件已迁移。
  • Canvas 界面色与实验内容色已分类,主题变化会重绘。
  • 启动窗口在深色模式下没有白色闪屏。
  • 浅色与深色正文对比度经过计算和设备观察。
  • pressed、selected、disabled、focused、error 均有清晰反馈。
  • 资源扫描与 base/dark 名称校验已进入日常检查。

二十七、源码事实与建议实现的边界

本文同时包含现状审计和迁移方案。为避免把示例资源、目标架构或验收标准误当成当前版本已经完成的功能,下面按源码可复核项逐一划清边界。

维度当前源码事实本文建议实现
颜色模式EntryAbility.onCreate()调用COLOR_MODE_LIGHT,应用固定浅色先完成资源迁移和双模式回归,再评估移除强制浅色
代码主题Theme.ets用static readonly string保存品牌、背景、文字和分类色保留类型与契约,把需随配置变化的颜色迁移为语义资源
字体令牌AppFonts集中 20/16/14/12 等字号与字重继续复用字号令牌,同时执行系统字体放大测试
间距与圆角Constants.ets定义页面边距、卡片间距和两级圆角将其纳入视觉契约,避免页面自行新增魔法数字
资源真源base/element/color.json与Theme.ets存在同义不同值指定资源系统为配置响应颜色的唯一真源
深色资源dark/element/color.json只有白色启动背景为所有语义颜色提供同名 dark 覆盖,并修正启动连续性
系统栏EntryAbility直接写浅色背景与深色内容色主题变化时成套更新背景、内容色和图标明暗策略
CanvasChartView.ets同时使用AppColors与#FFFFFF、#CCCCCC等硬编码将界面色注入绘制调色板,主题变化后清屏并重绘
实验内容色部分颜色表达试剂、火焰或分类含义与界面主题色分离,只有确有语义依据时保持固定
交互状态当前主题类未定义完整 pressed、focused、disabled、error 令牌按交互语义补齐状态,并在浅色和深色分别验证
对比度源码没有自动对比度校验流程对正文、图标、按钮、透明叠色和 Canvas 标签建立检查
构建结果本文未声称迁移方案已在该工程完成构建或真机验证每个迁移批次执行构建,并按页面与系统场景表回归

其中,强制浅色、两套颜色值、dark 目录内容和 Canvas 硬编码都来自当前工程;surface_page、content_primary等命名以及六批迁移顺序是建议方案。实施时应保留浅色基线截图和构建产物对照,不能把文章示例直接视为已经交付的源码。

二十八、结语

化学实验室已经拥有AppColors、AppFonts、间距与圆角常量,这说明项目具备统一视觉的基础;但强制浅色、双重颜色真源、dark 资源缺失和 Canvas 硬编码,表明它尚未形成完整的配置响应主题。

最稳妥的升级路线不是立刻切换系统主题,而是先用真实源码盘点颜色来源,把“蓝色、白色、灰色”改写成“操作、表面、内容、边界和状态”等语义,再建立 base/dark 同名资源。随后按主页面、共用组件、二级页面、系统栏和 Canvas 分批迁移,每批都构建并执行明确的操作验收。

当业务页面不再判断深浅色、不再保存十六进制颜色,系统栏和 Canvas 也能消费同一主题契约时,视觉一致性才真正从设计约定变成工程能力。

参考资料

  1. Huawei Developer,深浅色颜色适配:https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/ui-dark-light-color-adaptation
  2. Huawei Developer,资源分类与访问:https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/resource-categories-and-access
  3. Huawei Developer,ArkUI 概述:https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkui-overview
  4. 项目源码:entry/src/main/ets/common/Theme.ets
  5. 项目源码:entry/src/main/ets/common/Constants.ets
  6. 项目源码:entry/src/main/ets/entryability/EntryAbility.ets
  7. 项目资源:entry/src/main/resources/base/element/color.json
  8. 项目资源:entry/src/main/resources/dark/element/color.json
  9. 项目源码:entry/src/main/ets/components/ChartView.ets

AI 辅助声明:本文由 AI 辅助完成源码梳理、结构校对与配图设计,技术结论均以文中列出的本地 ArkTS 源码和资源文件为依据,并由作者复核后发布。

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

Vue3——第 8 篇:组件通信全攻略(上)——Props 与 Emit

本篇定位&#xff1a;组件之间的数据传递是 Vue 应用开发的核心课题。本篇将深入讲解 Vue 3 中最基础也是最常用的通信方式——Props&#xff08;父传子&#xff09; 和 Emit&#xff08;子传父&#xff09;&#xff0c;并探索如何通过 v-model 在组件间实现双向绑定。读完本篇…

作者头像 李华
网站建设 2026/10/22 12:40:10

【机械制图与CAD实战(十八)】组合体的尺寸标注

1、组合体的尺寸分类2、尺寸基准1、尺寸基准&#xff1a;标注尺寸的起点。2、在三维空间中应有长、宽、高三个方向的尺寸基准。3、一般把组合体的重要端面、对称面、轴线作为尺寸基准。1、组合体的尺寸分类1&#xff09;定形尺寸&#xff1a;确定图形中各几何元素&#xff08;各…

作者头像 李华