尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

乒乓球口袋教练 HarmonyOS 学习应用(06):主题 Token 与球台视觉风格

乒乓球口袋教练 HarmonyOS 学习应用(06):主题 Token 与球台视觉风格
📅 发布时间:2026/7/30 12:06:45

一、视觉切换为什么不能直接改业务页面

球台绿、记分卡白底和深色背景都属于视觉语义;课程完成度、收藏和练习记录则属于业务事实。如果页面里散落着十几处颜色常量,切换深色模式时最容易把文本、分隔线和阴影遗漏,同时也诱发组件把视觉选择误当成业务状态。本项目把颜色收敛为 palette,把主题模式收敛为 system、light、dark 三个值。

// 2. 根据用户在设置页选择的 mode 写入对应 palette 到 AppStorage // 3. UI 用 @StorageProp('palette') 拿色,用 @StorageProp('is_dark') 切图标 / 阴影 export class ThemeManager { private static instance: ThemeManager | null = null; private listener: mediaquery.MediaQueryListener | null = null; private systemDark: boolean = false; private mode: ThemeMode = 'system'; static get(): ThemeManager { if (ThemeManager.instance === null) { ThemeManager.instance = new ThemeManager(); } return ThemeManager.instance; } // 应用启动时调用:从持久化恢复 mode(默认 system),订阅系统主题 init(persistedMode: ThemeMode, systemColorMode?: ConfigurationConstant.ColorMode): void { this.mode = persistedMode; AppStorage.setOrCreate<ThemeMode>(KEY_THEME_MODE, this.mode); this.listener = mediaquery.matchMediaSync('(prefers-color-scheme: dark)'); this.systemDark = this.listener.matches; this.updateSystemColorMode(systemColorMode, false); this.refreshSystemDark(false);

二、ThemeManager 如何确定当前调色板

ThemeManager 初始化时读取持久化的 theme_mode,并结合 mediaquery 监听系统颜色模式。它把 palette 与 is_dark 写进 AppStorage,页面通过 StorageProp 读取同一套 Token。这样课程卡片、设置页和首页并不需要各自监听系统事件,视觉更新仍能由一个管理器完成。

参与者输入输出或约束
模型或配置稳定标识、模式或模块字段给出可追溯的工程事实
服务或系统能力经过归一化的请求返回明确结果或失败原因
页面回读后的结果只渲染,不保存第二份事实
} setMode(mode: ThemeMode): void { this.mode = mode; AppStorage.setOrCreate<ThemeMode>(KEY_THEME_MODE, mode); if (mode === 'system') { this.refreshSystemDark(false); } this.applyPalette(); } private resolveDark(): boolean { if (this.mode === 'dark') return true; if (this.mode === 'light') return false; return this.systemDark; } private applyPalette(): void { const isDark: boolean = this.resolveDark(); const palette: ColorPalette = isDark ? DarkPalette : LightPalette; AppStorage.setOrCreate<boolean>(KEY_IS_DARK, isDark); AppStorage.setOrCreate<ColorPalette>(KEY_PALETTE, palette); }

三、设置页只提交模式而不拼接颜色

设置页的单选项只调用 ThemeManager.get().setMode(m.id)。setMode 先写入 theme_mode,再依据模式调用 apply;它不修改课程模型,也不会清空正在输入的搜索词。这个边界很重要:用户回到课程页看到的是同一份学习数据换了一套色彩,而不是一次看起来像“刷新成功”的数据重置。

.onClick(() => { this.themeMode = m.id; ThemeManager.get().setMode(m.id); PreferencesHelper.get().persist('theme_mode', m.id); }); if (i < MODE_OPTIONS.length - 1) { Column().width('92%').height(0.5).backgroundColor(this.palette.divider); } }, (m: ModeOption) => m.id); } .width('100%') .backgroundColor(this.palette.card) .borderRadius(AppSizes.r3) .clip(true); } .alignItems(HorizontalAlign.Start) .width('100%'); } @Builder fontSection() { Column({ space: AppSizes.s2 }) { Text('字体大小')

四、系统主题变化与人工选择怎样区分

system 模式与 dark 模式不能混为一谈。前者允许监听器随系统变化,后者是用户明确锁定深色。当用户从 system 改为 light 后,系统再次变暗不应覆盖其选择;重新选回 system 才恢复监听。若不区分这两条路径,设置页的显示值会和实际调色板发生错位。

情况容易出现的错误本文采用的处理
数据或配置缺项伪造默认成功状态停在可解释的失败或空态
页面重进使用上一页残留对象从模型、服务或系统重新回读
重复动作再写一遍相同业务事实由稳定入口或回调收敛
} export const LightPalette: ColorPalette = { primary: '#0A84FF', primaryEnd: '#5B5BF0', accent: '#FF8A00', bg: '#F5F7FA', bgElevated: '#FFFFFF', card: '#FFFFFF', cardOverlay: '#00000010', divider: '#EAECEF', textPrimary: '#1A1A1F', textSecondary: '#5A6072', textTertiary: '#9097A5', textOnPrimary: '#FFFFFF', success: '#34C759', danger: '#FF3B30', badgeBg: '#E6F0FF', badgeText: '#0A84FF', tabActive: '#0A84FF', tabInactive: '#9097A5', shadow: '#0F1A3320', scrim: '#00000066'

五、切换后的可读性如何回读

验证先在设置页依次选择浅色、深色和跟随系统,分别进入首页和课程卡片回读背景、主文字和辅助文字的对比;再返回设置页确认选中项与主题一致;最后重启应用,检查 theme_mode 恢复而课程进度没有变化。配图展示的是深色设置状态,不能替代对另两种模式的检查。

验收阶段实际动作回读重点
前置确认启动正确 bundle 或打开目标页标题、入口与模块身份
主题操作执行搜索、切换、完成或跳转服务/系统返回的结果
重进检查返回、重启或切换范围后再进入事实没有依赖旧页面残留

六、实现边界与维护顺序

深浅色切换只改主题模式和调色板 Token,课程内容、进度与输入状态不随视觉模式发生第二份写入。 新增需求时应先补齐模型、配置或服务合同,再调整页面入口;把同一个判断复制到多个组件,短期看似方便,后续会使结果无法回读。ArkTS 状态管理的基础机制可参考 HarmonyOS 官方文档。

七、继续扩展时的约束

调色板的变化范围应当只包括表现层。课程模型、视频位置、练习日志和测验成绩即使被写入 AppStorage,也不能和 theme_mode 使用同一个含义含混的键。主题状态越独立,越能避免一次皮肤升级被误判为学习数据迁移。

深色模式的验收要注意可读不是只有文字没有消失。辅助说明、时间戳、未解锁徽章、禁用按钮和卡片边线在低亮度背景上也要保持区分度。把这些元素的角色写进 palette,可以让设计调整只影响 Token,而不是让每一个页面临时增加深色分支。

如果设备系统颜色变化发生在设置页之外,页面重新出现时应订阅已经更新的 palette,而不需要导航栈逐页重建。这个体验依赖 ThemeManager 的唯一实例,因此模块初始化和销毁时要避免重复注册监听器。

Token 不能被组件私自覆盖

组件可以根据 is_dark 选择图标资源,却不应在局部把文本颜色改成另一套固定色。局部覆盖一多,设置页显示深色而课程页仍有浅色残留的问题就无法从 ThemeManager 追踪。需要新增视觉角色时,应先扩展 palette 定义,再让组件消费这个名字明确的角色。

设置值的恢复顺序

应用重新启动后先恢复 theme_mode,再生成 palette,最后让页面读取 StorageProp。若先渲染页面再异步补颜色,用户会看到短暂的闪白;若恢复失败,则使用明确的 system 默认值并允许在设置页重新选择,而不是留下半初始化的颜色对象。

相关新闻

  • 从业者视角:智微工业工控机为何成为激光行业的主流选型参考
  • Multisim仿真调幅电路:从原理到实践,掌握AM调制与解调
  • Codex 工程化落地指南 05:.codex/config.toml 与权限配置——沙箱: 审批、网络访问与可信项目

最新新闻

  • Dev-C++新手入门指南:轻量IDE安装配置与C语言编程实践
  • GRAM模型原生安全实战:预训练阶段管控AI能力边界完整教程
  • 常州本地家电维修师傅电话推荐|本地维修家电|欧米到家统一报修
  • ESP32 Arduino下载速度慢?三招提速方案让烧录飞起来
  • Win11Debloat:Windows系统优化的模块化架构实践
  • 2026知名三维测力台厂家推荐 4大核心维度对比选购 - 资讯速览

日新闻

  • 终极TeamSpeak3音乐机器人搭建指南:5分钟实现语音聊天室音频播放
  • 广州海珠区内搬家攻略,平价靠谱搬家服务商推荐,专业打包搬运省心避坑全流程指南 - 厚道搬家
  • 大语言模型入门指南:从零到精通掌握AI核心技术的5大步骤

周新闻

  • 大连理工大学与东京大学联手打造的“主动型AI助手“
  • 170.2026年国家级科研瓶颈:超精密单点金刚石切削(SPDT)光学表面生成
  • SongBloom:革命性歌曲生成框架深度解析——如何通过交织自回归与扩散模型创作完整音乐

月新闻

  • 2026年6月公司网站搭建最新热门渠道测评:四大低成本/零代码平台对比+避坑
  • 【Linux】Linux arm 编译QT程序,出现expected “}“报错
  • 【MATLAB例程】四基站二维AOA定位与距离辅助增强对比仿真。基于角度观测和测距修正的固定目标平面定位精度分析

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号