HarmonyOS7 暗黑模式:3 步让你的 App 支持深色主题
文章目录前言为什么要适配暗黑模式颜色资源定义亮色模式颜色base/element/color.json暗黑模式颜色dark/element/color.json3 步适配第一步配置 module.json5第二步资源文件按目录组织第三步监听模式切换动态切换图片资源适配系统监听写在最后前言我之前上架一个 App审核直接打回来了——原因就是没适配暗黑模式。说实话当时挺不爽的但用了几天暗黑模式后真香了。HarmonyOS7 的暗黑模式适配其实没那么难3 步就能搞定今天手把手教你。暗黑模式不是换个黑色背景那么简单。文字颜色、图片资源、分割线、阴影——所有视觉元素都得跟着调。如果硬编码颜色值适配起来就是灾难。核心思路是所有颜色和图片都走资源引用系统自动帮你切换。为什么要适配暗黑模式除了审核要求还有几个实际好处省电——OLED 屏幕上黑色像素不发光暗黑模式真的能省电护眼——夜间使用时白色背景太刺眼暗黑模式舒服多了高级感——说实话很多 App 暗黑模式就是比亮色好看如果实在不想适配可以强制锁定亮色模式。但这招不推荐迟早得改。强制亮色的兜底代码不推荐但你知道有这招letapplicationContextthis.context.getApplicationContext()applicationContext.setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_LIGHT)颜色资源定义适配暗黑模式的第一步把所有硬编码的颜色值抽到资源文件里。亮色模式颜色base/element/color.json{color:[{name:app_background,value:#FFFFFF},{name:app_title_color,value:#000000},{name:app_subtitle_color,value:#666666},{name:app_divider,value:#E5E5E5},{name:app_primary,value:#007DFF}]}暗黑模式颜色dark/element/color.json{color:[{name:app_background,value:#1A1A1A},{name:app_title_color,value:#E6E6E6},{name:app_subtitle_color,value:#999999},{name:app_divider,value:#333333},{name:app_primary,value:#317AF7}]}关键点两个文件的name必须完全一致系统根据 name 匹配当前模式是暗黑就用dark目录下的值否则用base目录的。你代码里只需要写$r(app.color.app_background)剩下的系统全包了。3 步适配第一步配置 module.json5确认你的应用没有强制锁定颜色模式。默认情况下应用会跟随系统不需要额外配置。如果你之前加了colorMode配置删掉就行。第二步资源文件按目录组织目录结构长这样resources/ ├── base/ │ └── element/ │ └── color.json ← 亮色模式颜色 ├── dark/ │ └── element/ │ └── color.json ← 暗黑模式颜色 └── rawfile/在代码中引用颜色资源EntryComponentstruct DarkModeDemo{build(){Column(){Text(标题文字).fontSize(20).fontWeight(FontWeight.Bold).fontColor($r(app.color.app_title_color))Text(副标题).fontSize(14).fontColor($r(app.color.app_subtitle_color))Divider().color($r(app.color.app_divider))}.width(100%).height(100%).backgroundColor($r(app.color.app_background)).padding(16)}}注意背景色、文字色、分割线色——全部用$r()引用一个硬编码的#xxx都不要留。第三步监听模式切换有些场景需要在代码中感知暗黑模式变化比如需要更新 Web 组件的背景色。import{Configuration,UIAbility,ConfigurationConstant}fromkit.AbilityKitexportdefaultclassEntryAbilityextendsUIAbility{onConfigurationUpdate(newConfig:Configuration):void{AppStorage.setOrCreate(colorMode,newConfig.colorMode)}}解释onConfigurationUpdate在系统模式变化时触发把当前colorMode存到AppStorage全局可用。在页面中监听变化EntryComponentstruct ThemeAwarePage{StorageLink(colorMode)Watch(onColorModeChange)colorMode:ConfigurationConstant.ColorModeConfigurationConstant.ColorMode.COLOR_MODE_NOT_SETonColorModeChange(){if(this.colorModeConfigurationConstant.ColorMode.COLOR_MODE_DARK){console.info(切换到暗黑模式)}else{console.info(切换到亮色模式)}}build(){Column(){Text(主题感知页面).fontColor($r(app.color.app_title_color))}.width(100%).height(100%).backgroundColor($r(app.color.app_background))}}StorageLink双向绑定AppStorage中的值Watch在值变化时触发回调。这两个装饰器配合实现模式切换的即时响应。动态切换有时候用户想在 App 内手动切换主题不走系统设置。可以这样实现EntryComponentstruct ManualThemeSwitch{StorageLink(colorMode)colorMode:ConfigurationConstant.ColorModeConfigurationConstant.ColorMode.COLOR_MODE_NOT_SETStateisDark:booleanfalsetoggleTheme(){this.isDark!this.isDarkletapplicationContextgetContext(this).getApplicationContext()if(this.isDark){applicationContext.setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_DARK)}else{applicationContext.setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_LIGHT)}}build(){Column(){Toggle({type:ToggleType.Switch,isOn:this.isDark}).onChange((isOn:boolean){this.toggleTheme()})Text(手动切换主题).fontColor($r(app.color.app_title_color)).margin({top:20})}.width(100%).height(100%).justifyContent(FlexAlign.Center).backgroundColor($r(app.color.app_background))}}setColorMode可以主动设置应用的颜色模式不跟随系统。但用了这个方法后应用就不再自动跟随系统了除非你再次调用时传入COLOR_MODE_NOT_SET。图片资源适配颜色有dark目录图片也一样。把暗黑模式下的同名图片放到dark/media/目录resources/ ├── base/ │ ├── element/color.json │ └── media/ │ └── logo.png ← 亮色模式图片 └── dark/ ├── element/color.json └── media/ └── logo.png ← 暗黑模式图片代码中正常引用系统自动切换Image($r(app.media.logo)).width(100).height(100)对于 SVG 图标还有更省事的办法——用fillColor动态改颜色不用准备两套图Image($r(app.media.icon_svg)).width(24).height(24).fillColor($r(app.color.app_title_color))这招真香一个 SVG 文件配合颜色资源就能适配两种模式省了双倍图片资源。系统监听还有一个更快的方式直接用系统预置资源。HarmonyOS 提供了sys.color系列资源本身就适配了暗黑模式Text(使用系统配色).fontColor($r(sys.color.ohos_id_color_text_primary))用系统资源的好处是零配置不用建dark目录。缺点是你的 App 会跟着系统风格走没法做个性化定制。写在最后暗黑模式适配的核心就是一句话别硬编码颜色和图片全走资源引用。只要做到这一点3 步就能搞定建立dark资源目录所有视觉元素用$r()引用需要时监听模式变化提前做好适配比后面补不知道省多少事。等项目大了再回来改硬编码的颜色值那个痛苦你不想体验的。

相关新闻

闲鱼接单到产品化:我把一个 ¥800 的外包做成了可复制的海外 SaaS

闲鱼接单到产品化:我把一个 ¥800 的外包做成了可复制的海外 SaaS

正文 我今年 19 岁,大二,计算机专业。半个月前我在闲鱼接了一个 800 的定制单:客户是卖 GPT 提示词的,要做一个"加密分发系统",让下家能用 API 调用他的提示词但看不到明文。 接的时候我以为是个一次性外包。…

2026/9/23 22:26:21 阅读更多 →
131号文件落地,医疗设备行业告别“躺赚”时代

131号文件落地,医疗设备行业告别“躺赚”时代

2026年7月14日,一份文件让整个医疗设备行业彻底失眠。国家卫健委、中医药管理局、疾控局三部门联合印发的《关于进一步做好公立医疗卫生机构医用设备集中采购工作的通知》(国卫财务函〔2026〕131号),业内称之为“医疗设备集采总纲…

2026/9/17 11:53:18 阅读更多 →
HarmonyOS7 WebView 混合开发:原生和 H5 通信的 4 种姿势

HarmonyOS7 WebView 混合开发:原生和 H5 通信的 4 种姿势

文章目录前言WebView 基础搭建4 种通信方式对比JS 调原生:javaScriptProxy原生调 JS:runJavaScriptCookie 与登录态踩坑:白屏问题写在最后前言 做移动开发,纯原生的项目越来越少了。老板要快、要省钱、要热更新,H5 混…

2026/9/18 14:58:11 阅读更多 →

最新新闻

Dart List详解:从增删改查到Flutter实战与踩坑

Dart List详解:从增删改查到Flutter实战与踩坑

把Dart的列表单独拎出来写一篇笔记,起初我是拒绝的——列表嘛,哪个语言没有,不就是增删改查。但真正在Flutter里写了几个页面之后,才发现这个想法太天真。列表在Dart里不只是数据结构,更是业务数据流转的主要载体&…

2026/9/24 20:52:01 阅读更多 →
使用 /add-test Skill 为 vscode-gitlens 生成单元测试与 E2E 测试:完整实战指南

使用 /add-test Skill 为 vscode-gitlens 生成单元测试与 E2E 测试:完整实战指南

开发工具版本控制 【免费下载链接】vscode-gitlens Supercharge Git inside VS Code and unlock untapped knowledge within each repository — Visualize code authorship at a glance via Git blame annotations and CodeLens, seamlessly navigate and explore Git reposit…

2026/9/24 20:52:01 阅读更多 →
GTX 1060跑35B大模型?llama.cpp+MoE架构的五大优化技巧

GTX 1060跑35B大模型?llama.cpp+MoE架构的五大优化技巧

GTX 1060算是一张被反复“宣判退役”但又始终活跃在玩家和折腾党手里的老卡。6GB显存在今天连个大点的游戏都喂不饱,更别说跑大模型了。但llama.cpp这个项目偏偏把门槛压得很低——低到让这张2016年的卡,能带着Qwen 3.6 35B A3B这样的35B参数级MoE模型跑…

2026/9/24 20:52:01 阅读更多 →
城市电网负荷预测实操:BP神经网络入门与避坑指南

城市电网负荷预测实操:BP神经网络入门与避坑指南

简介:基于MATLAB实现的BP神经网络城市电网负荷预测项目,面向电力系统、自动化及相关专业的本科及以上学习者,可用于课程设计、毕业设计或负荷预测算法的快速验证,从数据导入、网络训练到结果评估均有完整实现。资源共11个文件&…

2026/9/24 20:52:01 阅读更多 →
通用智能体直接能用吗?稳定性、成本与二次加工实战指南

通用智能体直接能用吗?稳定性、成本与二次加工实战指南

我最近被问得最多的一个问题,就是标题这句:“现在的通用智能体这么强,直接用不行吗?” 每次去企业聊AI落地,演示完各家通用智能体平台的能力之后,业务方基本都会冒出这句话。语气里带着兴奋,也带…

2026/9/24 20:52:00 阅读更多 →
考虑交通流量的电动汽车充电站规划Matlab实现与优化

考虑交通流量的电动汽车充电站规划Matlab实现与优化

搞电动汽车充电站规划的人,十有八九都会被一个问题卡住:明明建了不少站,用户还是觉得不好用,运营商还是觉得不赚钱。问题出在哪?出在“站是拍脑袋定的”。真正靠谱的做法,应该是让数据说话,尤其…

2026/9/24 20:51:00 阅读更多 →

日新闻

基于YOLOv8的渔船作业监控系统:从环境搭建到边缘部署全流程

基于YOLOv8的渔船作业监控系统:从环境搭建到边缘部署全流程

简介:这是一套面向计算机、人工智能、自动化等专业学生与教师的毕业设计级项目资源,围绕YOLOv8实现渔船作业监控系统,可用于毕设、课程设计、大作业或项目立项演示。压缩包共97个文件,约24.21MB,以70个Python源码文件为…

2026/9/24 0:00:19 阅读更多 →
单细胞注释实战:基于Scanpy的标记基因与参考映射流程解析

单细胞注释实战:基于Scanpy的标记基因与参考映射流程解析

简介:一份基于单细胞RNA测序数据的细胞类型注释算法研究Python毕业设计源码,针对计算机相关专业正在做毕设或需要项目实战的学习者,可用于课程设计与期末大作业。项目代码完整、经导师指导评审通过,可直接运行,覆盖数据…

2026/9/24 0:00:19 阅读更多 →
C#源生成器实战:用增量生成器替代反射,告别AOT崩溃

C#源生成器实战:用增量生成器替代反射,告别AOT崩溃

第一次在项目里被反射卡住,是在一个老旧的WinForms模块里:几十个类依赖PropertyChanged通知,运行时反射读属性、发通知,每次启动慢半拍不说,一上.NET Native/AOT裁剪模式几乎全面崩盘。后来我把这段逻辑全部改成C#源生…

2026/9/24 0:00:19 阅读更多 →

周新闻

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

直接铺开项目本身吧。这几个月我一直在折腾一件事:用Flutter给OpenHarmony做一款游戏集合类的App,说白了就是把若干小游戏塞进一个壳里,用统一入口分发。这个方向本身不算新鲜,真正让我花了不少心思的,是首页那堆游戏卡…

2026/9/24 14:34:13 阅读更多 →
Word表格编号全攻略:从列表编号到题注交叉引用

Word表格编号全攻略:从列表编号到题注交叉引用

写Word文档,最让人头疼的往往是那些“看起来不起眼”的小问题。比如表格编号这事:今天在表后面多加了两个空白行,明天给客户交稿前发现整个章节的编号全部错位,光是挨个改序号就能耗掉大半个下午。我前阵子帮人整理一份上百页的技…

2026/9/24 9:10:42 阅读更多 →
从第一个站到第二个站:独立开发者的静态网站选型与落地实践

从第一个站到第二个站:独立开发者的静态网站选型与落地实践

1. 项目概述1.1 核心需求解析做独立开发者这几年,说实话,第一个网站上线的那天晚上我兴奋得没睡着。但等它跑了半年,流量惨淡、功能臃肿、代码自己都懒得看第二遍之后,我才慢慢琢磨明白一个道理:第一个网站是练手&…

2026/9/24 14:33:56 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/24 12:50:34 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/24 14:33:48 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/24 12:49:17 阅读更多 →