及时做APP开发实战(十)-深浅色主题适配实现 及时做APP开发实战(十)-深浅色主题适配实现本文将详细介绍如何在HarmonyOS NEXT中实现深浅色主题适配让应用跟随系统主题动态切换。一、需求背景1.1 功能需求现代应用需要支持深浅色主题切换提供更好的用户体验┌─────────────────────────────────────┐ │ 主题适配需求 │ ├─────────────────────────────────────┤ │ • 跟随系统主题自动切换 │ │ • 动态更新所有UI组件颜色 │ │ • 保持主题切换的流畅性 │ │ • 抽离颜色常量便于维护 │ └─────────────────────────────────────┘1.2 技术方案HarmonyOS提供Configuration.colorMode监听系统主题变化模式说明COLOR_MODE_LIGHT浅色模式COLOR_MODE_DARK深色模式COLOR_MODE_NOT_SET跟随系统二、主题颜色设计2.1 颜色体系规划【图1颜色体系】┌─────────────────────────────────────┐ │ 颜色分类 │ ├─────────────────────────────────────┤ │ 背景色 │ │ - 页面背景 background │ │ - 卡片背景 cardBackground │ │ │ │ 文本色 │ │ - 主文本 textPrimary │ │ - 次要文本 textSecondary │ │ - 提示文本 textHint │ │ │ │ 主题色 │ │ - 主色 primary │ │ - 主色浅 primaryLight │ │ - 成功色 success │ │ - 警告色 warning │ │ │ │ 边框色 │ │ - 边框 border │ │ - 分割线 divider │ └─────────────────────────────────────┘2.2 ThemeColors接口定义exportinterfaceThemeColors{// 背景色background:string;cardBackground:string;// 文本色textPrimary:string;textSecondary:string;textHint:string;// 主题色primary:string;primaryLight:string;success:string;warning:string;// 边框色border:string;divider:string;}2.3 浅色主题配置constLightTheme:ThemeColors{background:#F5F5F5,cardBackground:#FFFFFF,textPrimary:#333333,textSecondary:#666666,textHint:#999999,primary:#FF6B6B,primaryLight:#FFE5E5,success:#4CAF50,warning:#FF9800,border:#E0E0E0,divider:#EEEEEE};2.4 深色主题配置constDarkTheme:ThemeColors{background:#1A1A1A,cardBackground:#2D2D2D,textPrimary:#FFFFFF,textSecondary:#B0B0B0,textHint:#808080,primary:#FF6B6B,primaryLight:#3D2D2D,success:#66BB6A,warning:#FFB74D,border:#404040,divider:#333333};三、ThemeUtil工具类实现3.1 类结构设计┌─────────────────────────────────────┐ │ ThemeUtil │ ├─────────────────────────────────────┤ │ - instance: ThemeUtil │ │ - currentTheme: ThemeColors │ │ - isDarkMode: boolean │ ├─────────────────────────────────────┤ │ getInstance(): ThemeUtil │ │ updateTheme(config): void │ │ getColors(): ThemeColors │ │ isDark(): boolean │ │ getBackgroundColor(): string │ │ getCardBackground(): string │ │ getTextPrimary(): string │ │ ...其他getter方法 │ └─────────────────────────────────────┘3.2 完整实现代码importConfigurationConstantfromohos.app.ability.ConfigurationConstant;import{Configuration}fromkit.AbilityKit;// 主题颜色接口同上exportinterfaceThemeColors{...}// 主题配置同上constLightTheme:ThemeColors{...};constDarkTheme:ThemeColors{...};exportclassThemeUtil{privatestaticinstance:ThemeUtil|nullnull;privatecurrentTheme:ThemeColorsLightTheme;privateisDarkMode:booleanfalse;// 私有构造函数privateconstructor(){}// 获取单例publicstaticgetInstance():ThemeUtil{if(!ThemeUtil.instance){ThemeUtil.instancenewThemeUtil();}returnThemeUtil.instance;}/** * 根据配置更新主题 */publicupdateTheme(configuration:Configuration):void{try{constcolorModeconfiguration.colorMode;this.isDarkModecolorModeConfigurationConstant.ColorMode.COLOR_MODE_DARK;this.currentThemethis.isDarkMode?DarkTheme:LightTheme;console.info([ThemeUtil] 主题已更新:${this.isDarkMode?深色:浅色});}catch(err){consterrorMsgerrinstanceofError?err.message:String(err);console.error([ThemeUtil] 更新主题失败:${errorMsg});}}/** * 获取当前主题颜色 */publicgetColors():ThemeColors{returnthis.currentTheme;}/** * 是否深色模式 */publicisDark():boolean{returnthis.isDarkMode;}// 其他getter方法...publicgetBackgroundColor():string{returnthis.currentTheme.background;}publicgetCardBackground():string{returnthis.currentTheme.cardBackground;}publicgetTextPrimary():string{returnthis.currentTheme.textPrimary;}publicgetTextSecondary():string{returnthis.currentTheme.textSecondary;}publicgetTextHint():string{returnthis.currentTheme.textHint;}publicgetPrimary():string{returnthis.currentTheme.primary;}publicgetSuccess():string{returnthis.currentTheme.success;}publicgetBorder():string{returnthis.currentTheme.border;}}四、Ability中监听主题变化4.1 在EntryAbility中添加监听import{AbilityConstant,ConfigurationConstant,UIAbility,Want,Configuration}fromkit.AbilityKit;import{ThemeUtil}from../utils/ThemeUtil;exportdefaultclassEntryAbilityextendsUIAbility{onCreate(want:Want,launchParam:AbilityConstant.LaunchParam):void{// 设置跟随系统主题try{this.context.getApplicationContext().setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET);}catch(err){hilog.error(DOMAIN,testTag,Failed to set colorMode);}}/** * 监听系统配置变化包括主题变化 */onConfigurationUpdate(newConfig:Configuration):void{hilog.info(DOMAIN,testTag,Configuration updated);// 更新主题try{ThemeUtil.getInstance().updateTheme(newConfig);}catch(err){hilog.error(DOMAIN,testTag,Failed to update theme);}}}4.2 配置变化流程【图2主题切换流程】┌─────────────────────────────────────┐ │ 主题切换流程 │ ├─────────────────────────────────────┤ │ 用户切换系统主题 │ │ ↓ │ │ 系统发送Configuration变化事件 │ │ ↓ │ │ EntryAbility.onConfigurationUpdate │ │ ↓ │ │ ThemeUtil.updateTheme() │ │ ↓ │ │ 更新currentTheme和isDarkMode │ │ ↓ │ │ UI组件响应式更新 │ └─────────────────────────────────────┘五、页面中使用主题5.1 定义主题状态变量import{ThemeUtil,ThemeColors}from../utils/ThemeUtil;EntryComponentstruct PomodoroPage{// 主题状态StatethemeColors:ThemeColorsThemeUtil.getInstance().getColors();StateisDarkMode:booleanfalse;// 工具类privatethemeUtil:ThemeUtilThemeUtil.getInstance();// 生命周期asyncaboutToAppear(){// 初始化主题this.themeColorsthis.themeUtil.getColors();this.isDarkModethis.themeUtil.isDark();}}5.2 在UI组件中应用主题颜色BuilderTopBar(){Row(){Text( 番茄钟).fontSize(24).fontWeight(FontWeight.Bold).fontColor(#FFFFFF)}.width(100%).height(56).backgroundColor(this.isBreak?this.themeColors.success:this.themeColors.primary)}BuilderTimerSection(){Column(){// 进度条Progress({value:this.getProgress(),total:100,type:ProgressType.Ring}).color(this.isBreak?this.themeColors.success:this.themeColors.primary).backgroundColor(this.themeColors.border)// 时间显示Text(this.formatTime(this.timeLeft)).fontSize(64).fontWeight(FontWeight.Bold).fontColor(this.themeColors.textPrimary)}.width(100%).backgroundColor(this.themeColors.background)}BuilderPomodoroStats(){Column(){Row(){Column(){Text(this.pomodoroCount.toString()).fontSize(28).fontWeight(FontWeight.Bold).fontColor(this.themeColors.primary)Text(今日完成).fontSize(12).fontColor(this.themeColors.textSecondary)}}}.backgroundColor(this.themeColors.cardBackground)}5.3 半模态弹窗主题适配.bindSheet($$this.showTimePicker,this.TimePickerSheet(),{height:300,backgroundColor:this.isDarkMode?#2D2D2D:Color.White,dragBar:true,onWillDismiss:(){this.showTimePickerfalse;}})六、颜色对比效果6.1 浅色主题效果【图3浅色主题】6.2 深色主题效果【图4深色主题】七、最佳实践7.1 颜色使用规范// ✅ 推荐使用主题颜色.backgroundColor(this.themeColors.background).fontColor(this.themeColors.textPrimary)// ❌ 不推荐硬编码颜色.backgroundColor(#F5F5F5).fontColor(#333333)7.2 状态变量设计// ✅ 推荐使用State自动响应StatethemeColors:ThemeColorsThemeUtil.getInstance().getColors();// ❌ 不推荐普通变量不会触发更新privatethemeColors:ThemeColorsThemeUtil.getInstance().getColors();7.3 主题颜色扩展// 扩展主题颜色接口exportinterfaceThemeColors{// 基础颜色...// 扩展颜色error:string;// 错误色info:string;// 信息色disabled:string;// 禁用色}// 在主题配置中添加constLightTheme:ThemeColors{// 基础颜色...error:#F44336,info:#2196F3,disabled:#BDBDBD};八、总结本文实现了番茄钟应用的深浅色主题适配颜色体系设计定义完整的ThemeColors接口工具类封装ThemeUtil单例类管理主题状态系统监听在Ability中监听配置变化响应式更新使用State实现UI自动更新主题适配是现代应用的基本要求合理的设计可以让应用在各种环境下都有良好的显示效果。

相关新闻

最新新闻

SerenityOS 命令行选项解析指南:getopt 与 getopt_long 用法、返回值与底层实现

SerenityOS 命令行选项解析指南:getopt 与 getopt_long 用法、返回值与底层实现

SerenityOS 命令行选项解析指南:getopt 与 getopt_long 用法、返回值与底层实现 【免费下载链接】serenity The Serenity Operating System 🐞 项目地址: https://gitcode.com/GitHub_Trending/se/serenity 导读 本文以 getopt(3) 手册 为核心&a…

2026/10/3 16:42:15
轻量服务器还是ECS?大促云服务器选购与避坑实战指南

轻量服务器还是ECS?大促云服务器选购与避坑实战指南

每年大促节点,群里永远有人在问同一个问题:“38元的轻量服务器到底怎么抢?为什么我每次点进去都是已售罄?68元直购和99元的ECS我到底选哪个?”作为一个常年帮团队和自己采购云服务器的老用户,我太清楚这种纠…

2026/10/3 16:42:30
为 AI 代理的 Review 动作编写 Cedar 审批门控策略:review-agent-governance 策略编写实战指南

为 AI 代理的 Review 动作编写 Cedar 审批门控策略:review-agent-governance 策略编写实战指南

为 AI 代理的 Review 动作编写 Cedar 审批门控策略:review-agent-governance 策略编写实战指南 【免费下载链接】agents Multi-harness agentic plugin marketplace for Claude Code, Codex, Cursor, OpenCode, GitHub Copilot, and Google Antigravity 项目地址:…

2026/10/3 16:42:22
PaddleOCR 手写数学公式识别算法 CAN 实战指南:Counting-Aware Network 训练、评估与推理部署

PaddleOCR 手写数学公式识别算法 CAN 实战指南:Counting-Aware Network 训练、评估与推理部署

PaddleOCR 手写数学公式识别算法 CAN 实战指南:Counting-Aware Network 训练、评估与推理部署 【免费下载链接】PaddleOCR Turn any PDF or image document into structured data for your AI. A powerful, lightweight OCR toolkit that bridges the gap between i…

2026/10/3 7:41:27
Spring源码解析:构造器注入的类型转换与候选匹配机制

Spring源码解析:构造器注入的类型转换与候选匹配机制

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/3 16:42:24
openai-agents-python 多模型接入指南:深入解析 AnyLLMModel 适配层与 any-llm 路由

openai-agents-python 多模型接入指南:深入解析 AnyLLMModel 适配层与 any-llm 路由

openai-agents-python 多模型接入指南:深入解析 AnyLLMModel 适配层与 any-llm 路由 【免费下载链接】openai-agents-python A lightweight, powerful framework for multi-agent workflows 项目地址: https://gitcode.com/GitHub_Trending/op/openai-agents-pyth…

2026/10/3 16:42:28

日新闻

周新闻

月新闻