在app中适配深色模式及切换深色模式 原创
1. 效果展示
2. 概述
在开发应用中,深色模式逐渐成为用户界面设计的重要组成部分。如果不在开发时,主动配置颜色资源来设置深色模式,这样在系统切换深色模式后,再次打开咱们的应用就会很丑。深色模式的实现方式,包括跟随系统变化和不跟随系统变化的两种场景。下面我就来介绍一下这两部分
3. 跟随系统变化
3.1 不设置深色模式
应用默认是跟随系统的颜色变化的,如果不想跟随系统颜色变化,不设置深色模式,避免系统深色模式给app的影响,就可以在应用的entryability中
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
this.context.getApplicationContext().setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET);
}
将枚举值COLOR_MODE_NOT_SET(未配置颜色模式)改为浅色模式
this.context.getApplicationContext().setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_LIGHT)
但是我们开发应用,肯定想让用户又更好的体验,所以最好还是要适配深色模式的。下面我就来详细解释怎么跟随系统设置深色模式
3.2 颜色资源适配
在工程的resources/dark/element/color.json和resources/base/element/color.json下面需要我的自己定义一些颜色资源的适配。
3.2.1 基于资源文件的组件颜色适配
示例
在base中适配浅色资源
{
"color": [
{
"name": "start_window_background",
"value": "#FFFFFF"
},
{
"name": "background_color",
"value": "#F5F5F5",
"additionalProperties": "全局背景颜色"
},
{
"name": "font_color",
"value": "#BEFF33",
"additionalProperties": "全局绿色文字"
},
{
"name": "main_font",
"value": "#000000",
"additionalProperties": "全局主字体颜色"
},
]
}
在dark中适配深色资源
{
"color": [
{
"name": "start_window_background",
"value": "#000000"
},
{
"name": "background_color",
"value": "#121212",
"additionalProperties": "全局背景颜色"
},
{
"name": "font_color",
"value": "#6B8E1D",
"additionalProperties": "全局绿色文字"
},
{
"name": "main_font",
"value": "#F6F6F6",
"additionalProperties": "全局主字体颜色"
},
]
}
这样我的就可以在开发中使用他们了,通过$r方式加载颜色资源的key值
@Entry
@Component
struct MyComponent {
build() {
Column() {
Text('Hello, World!')
.backgroundColor($r('app.color.background_color'))
}
}
}
3.2.2 基于媒体文件的图片资源适配
在resources/base/media和resources/dark/media中分别存放浅色和深色模式下的图片资源
对于png图片
示例
@Entry
@Component
struct Button{
build() {
Column() {
Image($r("app.media.add"))
}
}
}
对于svg图片
通过fillColor属性配合系统资源改变图片的绘制颜色。
示例
Image($r(modeImgMap.get(item.mode)))
.width(28)
.height(28)
.margin({ left: 10, right: 10 })
.fillColor(this.selectedTravelModeIndex === index ? '#5B5B5B' : $r('app.color.menu_font_color'))
3.2.3 基于Web组件适配
通过darkMode和forceDarkAccess属性配置Web组件的深色模式。
import web_webview from '@ohos.web.webview'
@Entry
@Component
struct MyComponent{
controller: web_webview.WebviewController = new web_webview.WebviewController()
@State mode: WebDarkMode = WebDarkMode.Auto
@State access: boolean = true
build() {
Column() {
Web({ src: 'www.baidu.com', controller: this.controller })
.darkMode(this.mode)
.forceDarkAccess(this.access)
}
}
}
4. 不跟随系统变化
4.1 通过setColorMode设置应用的颜色模式(自定义按钮更改)
我们可以在应用中自定义按钮来改变app的颜色模式,以便用户可以获得更佳的体验
上面的颜色资源适配还是老样子
示例
@Entry
@Component
export struct MyPage {
private context = getContext(this) as common.UIAbilityContext
@State isDarkMode: boolean = this.context.config.colorMode ? false : true;
build() {
Toggle({ type: ToggleType.Switch, isOn: this.isDarkMode })
.width(41)
.height(21)
.switchStyle({
unselectedColor: '#FFFFFF',
pointRadius: 9
})
.switchPointColor('#333333')
.selectedColor('#E9FAFF')
.borderRadius(25)
.border({ color: '#333333', width: 1 })
.margin({ right: 25 })
.onChange(() => {
//深色模式切换
this.isDarkMode = !this.isDarkMode;
this.context.getApplicationContext().setColorMode(this.isDarkMode ? 0 : 1);
});
}
}
当用户开关 Toggle 控件时,会触发 onChange 事件,代码中会更新 isDarkMode 状态变量的值,并调用 context.getApplicationContext().setColorMode() 方法来改变应用的颜色模式。
- 如果 isDarkMode 为 true,则设置颜色模式为 1(深色模式)。
- 如果 isDarkMode 为 false,则设置颜色模式为 0(浅色模式)。
这样就可以在应用中自己更改深色模式,无需跟随系统了
4.2 系统默认判断规则
- 如果应用调用上述setColorMode接口主动设置了深浅色,则以接口效果优先。
- 应用没有调用setColorMode接口时:
- 如果应用工程dark目录下有深色资源,则系统内置组件在深色模式下会自动切换成为深色。
- 如果应用工程dark目录下没有任何深色资源,则系统内置组件在深色模式下仍会保持浅色体验。
5. 总结
在ArkUI框架中实现深色模式适配是一个重要的任务,它能够显著提升用户在不同环境下的使用体验。我们介绍了两种实现深色模式的方式:跟随系统变化和不跟随系统变化。跟随系统变化时,可以通过设置颜色模式为 COLOR_MODE_NOT_SET 来确保应用自动适应系统设置,或者定义 resources/base/element/color.json 和 resources/dark/element/color.json 中的不同颜色资源,并分别准备浅色和深色模式下的图片资源。不跟随系统变化时,可以通过自定义按钮和 Toggle 控件来让用户手动切换颜色模式,并在 onChange 事件中更新颜色模式状态,确保应用能够根据用户的选择动态调整界面的颜色和图片资源。