鸿蒙5.0实战案例:基于原生能力的深色模式适配

devtools/2025/2/25 6:13:44/

往期推文全新看点(文中附带全新鸿蒙5.0全栈学习笔录)

✏️ 鸿蒙(HarmonyOS)北向开发知识点记录~

✏️ 鸿蒙(OpenHarmony)南向开发保姆级知识点汇总~

✏️ 鸿蒙应用开发与鸿蒙系统开发哪个更有前景?

✏️ 嵌入式开发适不适合做鸿蒙南向开发?看完这篇你就了解了~

✏️ 对于大前端开发来说,转鸿蒙开发究竟是福还是祸?

✏️ 鸿蒙岗位需求突增!移动端、PC端、IoT到底该怎么选?

✏️ 记录一场鸿蒙开发岗位面试经历~

✏️ 持续更新中……


场景描述

对于原生开发的应用,深色模式适配是开发过程中常见的业务场景,系统可以通过状态栏中的深色模式开关配置系统的颜色模式,当系统颜色模式方式变化时,应用经常会遇到如下的业务诉求:

场景一:跟随系统变化,感知系统颜色模式发生变化,无需重启应用,完成资源切换。

场景二:不跟随系统变化,应用固定使用某种颜色模式,不跟随系统颜色模式变化。

方案描述

场景一:跟随系统

效果

普通暗夜模式

方案

1.基于资源文件的组件颜色适配:

自定义两套颜色资源(resources/dark/element/color.json和resources/base/element/color.json),通过$r的方式加载颜色资源的key值。通过系统资源实现,开发者可直接使用的系统预置资源,即分层参数,同一资源ID在设备类型、深浅色等不同配置下有不同的取值。通过使用系统资源,不同的开发者可以开发出具有相同视觉风格的应用,不需要自定义2份颜色资源,在深浅色模式下也会自动切换成不同的颜色值。

2.基于媒体文件的图片资源适配:

采用资源限定词目录的方式,自定义两套资源(resources/dark/media和resources/base/media),通过$r的方式加载颜色资源的key值。

对于 SVG 格式的一些简单图标,可以使用 fillColor 属性配合系统资源改变图片的绘制颜色。不通过两套图片资源的方式,也可以实现深浅色模式适配(补充:通过两套图片资源的方式也可以实现,修改svg图片中fill属性的颜色,然后将两张图片分别放置在不同的目录下)

3.页面状态栏的适配:

此处的代码要用到窗口的属性来设置状态栏图标的颜色,写在entry下(参考此章核心代码1);值得一提的是,barContentColor并不支持使用$r的方式加载颜色资源的key值,它是一个string类型的,因此,这里的是不是暗夜模式就要开发者自己去写代码判断。

4.基于Web组件适配:

支持对前端页面进行深色模式设置,通过darkMode 接口可以配置跟随系统。若网页未定义深色样式,则需开启强制深色模式 forceDarkAccess 使用。需要注意的要让网页跟随系统,请设置WebDarkMode为Auto。

核心代码:

1.基于资源文件的组件颜色适配:

  1. resources/base/element/color.json

    {"name": "list_background","value": "#FFFFFF"},
    
  2. resources/dark/element/color.json

    {"name": "list_background","value": "#212224"},
    
  3. 通过$r的方式加载颜色资源的key值。

     .backgroundColor($r('app.color.list_background'))
    

2.基于媒体文件的图片资源适配:

1.普通png图片

  • resources/base/media

    路径resources/base/media/loading.png

  • resources/dark/media

    路径resources/dark/media/loading.png

  • 通过$r的方式加载颜色资源的key值

    Image($r("app.media.loading"))
    

2.svg图片

resources/base/color

{       "name": "ic_public_back_color",       "value": "#212121"     
}

esources/dark/color

{       "name": "ic_public_back_color",       "value": "#dcdcdc"     
}
  • 通过$r的方式加载颜色资源的key值,通过fillcolor修改svg颜色
Image($r('app.media.ic_public_back')).fillColor($r('app.color.ic_public_back_color'))

3.页面状态栏的适配:

  @State isDarkMode: boolean = false@State barContentColor: string = ''private context = getContext(this) as common.UIAbilityContext
// 状态栏适配黑夜模式onPageShow(): void {window.getLastWindow(getContext(this), (err, win) => {//判断是否是暗夜模式(因为有三种)if(this.context.config.colorMode==1){this.isDarkMode = false}if(this.context.config.colorMode==0){this.isDarkMode = true}//因为barContentColor只能取string类型的值,所以不能直接用resource资源来适配this.barContentColor = this.isDarkMode ? '#ffffff' : '#000000'let SystemBarProperties: window.SystemBarProperties = {statusBarContentColor: this.barContentColor};})}

4.基于Web组件适配:(注意开启了强制网页适配,原因是指定网页没有定义深色样式)

// xxx.ets
import web_webview from '@ohos.web.webview'
@Entry
@Component
struct WebComponent {controller: web_webview.WebviewController = new web_webview.WebviewController()@State mode: WebDarkMode = WebDarkMode.Auto@State access: boolean = truebuild() {Column() {Web({ src: 'www.xxx.com', controller: this.controller }).darkMode(this.mode).forceDarkAccess(this.access)}}
}

场景二:不跟随系统

效果

  1. setColorMode

方案

  • 通过setColorMode设置应用的颜色模式需要注意通过setColorMode改变模式,同样可以被this.context.config.colorMode以及onConfigurationOnUpdate监听
  • Web组件通过darkMode和forceDarkAccess属性,配置是否强制接入深色模式。

案例代码

1.通过setColorMode设置应用的颜色模式

@Entry
@Component
struct TogglePage2 {@State isDarkMode: boolean = falsebuild() {Column() {Toggle({ type: ToggleType.Switch ,isOn:this.isDarkMode})//isOn 属性值在有触发刷新页面的场景中,不要省略.onChange((isOn: boolean) => {console.log('Toggle.onChange2: isOn', isOn)this.isDarkMode = isOngetContext(this).getApplicationContext().setColorMode(this.isDarkMode?0:1) //触发二次渲染,渲染不给isOn 熟悉赋值会给默认值false,导致状态不对})}.width("100%").height("100%").padding(32)}
}

2.Web组件通过[darkMode]和[forceDarkAccess]属性,配置是否强制接入深色模式案例代码,设置darkMode为On即可

import web_webview from '@ohos.web.webview'@Entry
@Component
struct WebComponent {controller: web_webview.WebviewController = new web_webview.WebviewController()@State mode: WebDarkMode = WebDarkMode.On@State access: boolean = truebuild() {Column() {Web({ src: 'www.xxx.com', controller: this.controller }).darkMode(this.mode).forceDarkAccess(this.access)}}
}

http://www.ppmy.cn/devtools/161511.html

相关文章

HTML之JavaScript DOM编程获取元素的方式

HTML之JavaScript DOM编程获取元素的方式 1.获得document DOM树window.document(是window的属性)2.从document中获取要操作的元素1.直接获取var aaa document.getElementById("username") // 根据元素的id值获取页面上的唯一一个元素,有同名的则返回找到的第一个var…

java23种设计模式-原型模式

原型模式(Prototype Pattern)学习笔记 🌟 定义 原型模式属于创建型设计模式,通过复制现有对象(原型)来创建新对象,避免重复进行初始化操作。该模式的核心是实现对象的克隆能力。 &#x1f3af…

Java基础进阶提升

(一)Java基础 面向对象java语法常用类,api数据类型方法、对象、引用运算符、操作符关键字、关键词 (二)java进阶 异常、异常分类与处理线程同步、守护线程多线程、IO流接口、多继承jdk、jre、jvm反射、泛型类继承、方法覆盖 (三)数据库 Mysql数据库Oracle数据库…

Cookie 与 localStorage_浏览器存储机制全解析

1. 引言 在现代 Web 开发中,浏览器存储机制是不可或缺的一部分。无论是保存用户偏好、会话信息还是缓存数据,选择合适的存储方式对于提升用户体验和应用性能至关重要。本文将深入探讨两种常见的浏览器存储机制:Cookie 和 localStorage。我们将详细介绍它们的基本概念、应用…

Windows 11【1001问】Windows 11系统硬件配置要求

Windows 11 的设计目标是让用户更贴近自己喜欢的内容,在其发布之际,计算机在连接、创作以及游戏体验方面扮演了更加核心的角色。在设定 Windows 11 的最低系统要求时,我们依据三个关键原则来指导决策,以确保用户能够获得卓越的使用…

前缀和刷题-- LeetCode

文章目录 寻找数组的中心下标题解代码 巧克力题解代码 寻找数组的中心下标 题目 题解 1. 预处理前缀和和后缀和数组,注意边界问题,f(0) 0,g(n-1) 0 2. 然后遍历数组一遍,f[i] g[i],i就是下标 3. 时间复杂度是:O(N) 代码 cl…

从零开始玩转TensorFlow:小明的机器学习故事 5

图像识别的挑战 1 故事引入:小明的“图像识别”大赛 小明从学校里听说了一个有趣的比赛:“美食图像识别”。参赛者需要训练计算机,看一张食物照片(例如披萨、苹果、汉堡等),就能猜出这是什么食物。听起来…

2007年诺基亚内部对iPhone的竞争分析报告

2007年iPhone发布后,诺基亚内部至少有9名员工指出其触屏界面、互联网整合能力将颠覆市场,并建议开发同类产品,但高管因当时占据全球50%市场份额而轻视威胁,认为苹果的高价和虚拟键盘会限制其普及。 诺基亚虽然意识到需推出触屏手机…