前言
应用上架之前,如果你未考虑到深色模式,大概率会审核不通过,问题原因为:应用存在应用未适配深色模式显示问题,不符合鸿蒙应用UX设计规范。

当然了,如果你实在不想适配,也有一个取巧的办法,那就是暂不适配,统一设置为浅色模式。
TypeScript
// 设置应用为浅色模式
let applicationContext = this.context.getApplicationContext()
applicationContext.setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_LIGHT)
以上的代码设置之后,应用就不会跟随系统模式切换而切换了,但是,取巧终归是取巧,也许现在官方没有严格要求,但是不代表日后不会,所以,为了日后应用的上架,还有深色模式下能给用户带来不一样的体验,建议还是该适配就适配。
对于原生的页面,适配非常的简单,这个在之前的文章中也有过概述,两种方式,一种是资源的方式,一种是代码的方式。
资源方式
对于资源方式,我们可以在resources中新建dark,创建和浅色对应的颜色和图片资源即可,如下图所示:

比如,可以在color.json中定义同名配色并赋予不同的色值。
浅色模式:base/element/color.json文件:
TypeScript
{
"color": [
{
"name": "app_title_color",
"value": "#000000"
}
]
}
深色模式:dark/element/color.json文件:
TypeScript
{
"color": [
{
"name": "app_title_color",
"value": "#FFFFFF"
}
]
}
当然了,图片也是类似的,这里就不一一举例了。
代码方式
代码方式就需要监听系统模式的切换了,根据不同的模式,手动设置相应的颜色,基本操作如下,当然了,并不是唯一的方式。
在UIAbility的onConfigurationUpdate进行监听模式改变,这里可以通过事件分发或者通过应用级变量的状态管理AppStorage保存当前colorMode值。
TypeScript
import { Configuration, UIAbility } from '@kit.AbilityKit';
export default class EntryAbility extends UIAbility {
onConfigurationUpdate(newConfig: Configuration): void {
AppStorage.setOrCreate('colorMode', newConfig.colorMode);
}
}
在其他的页面就可以通过@StorageLink装饰器监听colorMode字段的变化,根据不同的状态设置对应的资源即可。
TypeScript
import { ConfigurationConstant } from '@kit.AbilityKit';
@StorageLink('colorMode') @Watch('colorModeChange') colorMode: ConfigurationConstant.ColorMode =
ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET;
/**
* 系统深色模式变化,可以重新设置主题
*/
colorModeChange() {
if (this.colorMode === ConfigurationConstant.ColorMode.COLOR_MODE_DARK) {
this.readerSetting.nightMode = true;
this.readerSetting.fontColor = '#ffffff';
this.readerSetting.themeColor = '#202224';
} else {
this.readerSetting.nightMode = false;
this.readerSetting.fontColor = '#000000';
this.readerSetting.themeColor = '#FFFFFF';
}
this.readerComponentController.setPageConfig(this.readerSetting);
}
以上的方式呢,都是原生的方式,很多的应用,除了原生渲染之外,还有着H5的渲染,针对H5页面,我们该如何动态切换深色和浅色模式呢?
方式一:加载不同模式的web页面
这种方式,说白了就是提供两个web页面,一个是浅色模式,一个是深色模式,我们检测到系统模式变化之后,动态的切换对应模式的页面即可,目前官方在某些功能里,也在使用这种方式,比如官方的一键登录功能,我们就可以发现,针对《认证协议》,就提供了一个浅色页面和一个深色页面。

基本代码如下:
TypeScript
controller?: WebviewController = new webview.WebviewController()
import { ConfigurationConstant } from '@kit.AbilityKit';
@StorageLink('colorMode') @Watch('colorModeChange') colorMode: ConfigurationConstant.ColorMode =
ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET;
/**
* 系统深色模式变化,可以重新设置主题
*/
colorModeChange() {
if (this.colorMode === ConfigurationConstant.ColorMode.COLOR_MODE_DARK) {
this.controller?.loadUrl("深色页面")
} else {
this.controller?.loadUrl("浅色页面")
}
this.readerComponentController.setPageConfig(this.readerSetting);
}
方式二:CSS样式适配
方式一,由于是不同的页面,在模式切换的时候,web组件会重新加载,会有一定的延时,不会立马模式转换,并且,在有多个不同的web页面的情况下,会占用服务器资源,当然也会给web前端同学增加一定工作量。
如何实现在本来的页面中进行模式的立马切换?这里就要说到CSS样式了,它可以让web页面根据系统模式进行快速切换,做到0延时,这也是在开发中推荐的,当然了,web前端同学的工作量该做还得做,这是少不了的。
web前端设置
在网页开发过程中,web前端同学可以使用color-scheme和prefers-color-scheme属性进行深色模式适配。
首先,在head标签中添加如下信息,这里的color-scheme是一个CSS属性,用于表示网页支持的配色方案,可以影响表单、滚动条和CSS系统颜色。CSS系统颜色指Web组件内置的颜色,是部分元素未定义样式时应用的默认颜色。
TypeScript
<meta name="color-scheme" content="light dark">
声明了meta之后,剩下的就是,深色和浅色的资源设置了,一般情况下我们只设置默认样式和深色样式即可,当然了你也可以使用浅色模式覆盖深色模式,样式的适配代码如下,只需要在不同模式下设置对应的资源即可。
TypeScript
<style>
/* 默认样式 */
body { background-color: White; }
/* 浅色样式,Web关闭深色模式时覆盖默认样式 */
@media (prefers-color-scheme: light) {
body { background-color: Gray; }
}
/* 深色样式,Web开启深色模式时覆盖默认样式 */
@media (prefers-color-scheme: dark) {
body { background-color: Black; }
}
</style>
prefers-color-scheme是CSS中的一个媒体查询功能,可以检测系统的主题颜色。web前端同学可以通过该特性,为不同的系统主题颜色定义不同的网页CSS样式,以适应用户的主题偏好。
Web深色模式设置
web前端同学在设置好对应模式资源之后,我们需要给web组件的适配模式打开,方可生效,也就是通过darkMode()配置Web深色模式,因为默认状态下为关闭,我们可以设置为WebDarkMode.Auto,让它跟随系统模式进行动态切换。
还有一个注意事项时,那就是web组件的背景颜色,也需要根据模式动态的切换,否则就会出现,深色模式下先白后改变的状态,简单案例如下:
TypeScript
import { webview } from '@kit.ArkWeb';
@Entry
@Component
struct WebComponent {
controller: webview.WebviewController = new webview.WebviewController();
@State isDark: boolean = false;
build() {
Column() {
Web({ src: $rawfile('index.html'), controller: this.controller })
.darkMode(WebDarkMode.Auto)
.backgroundColor(this.isDark ? Color.Black : Color.White)
}
}
}
以上的代码设置之后,便可实现了web页面动态的模式切换。
相关总结
web前端页除了css设置之外,还可以通过js代码来监听模式的改变,进行动态的资源设置。
TypeScript
// 监听颜色方案变化事件
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', (e) => {
let isDark = e.matches;//是否是深色模式
});
对于深色模式,建议提前去做,因为到后面再想起来适配,需要全方位的资源替换,还要进行系统的测试验证,比较耗费时间和精力,所以,项目一开始,我们尽量把深色模式考虑进去。