鸿蒙开发实践——基于原生能力的深色模式适配

场景描述

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

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

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

方案描述

场景一:跟随系统

效果

普通暗夜模式

方案

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

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

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

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

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

3.页面状态栏的适配:

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

4.基于Web组件适配:

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

DD一下:在探索鸿蒙系统的学习过程中,不少人都曾遇到过各种棘手问题。小编结合自身学习与实践经历,将容易踩坑的环节和对应的解决思路整理成攻略,希望这些经验分享能为同样在学习鸿蒙的伙伴们提供一些参考和帮助:

请移步前往小编鸿蒙全栈开发学习指南 ​

1.鸿蒙全栈开发学习路线
2.OpenHarmony开发基础
3.OpenHarmony北向开发环境搭建
4.鸿蒙南向开发环境的搭建
5.鸿蒙生态应用开发白皮书V2.0 & V3.0
6.鸿蒙开发面试真题(含参考答案) 
7.TypeScript入门学习手册
8.OpenHarmony 经典面试题(含参考答案)
9.OpenHarmony设备开发入门【最新版】
10.沉浸式剖析OpenHarmony源代码
11.系统定制指南
12.【OpenHarmony】Uboot 驱动加载流程
13.OpenHarmony构建系统--GN与子系统、部件、模块详解
14.ohos开机init启动流程
15.鸿蒙版性能优化指南
......

核心代码:

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组件适配:(注意开启了强制网页适配,原因是指定网页没有定义深色样式)

 @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
      };
    })
  }

场景二:不跟随系统

效果

  1. setColorMode

方案

  • 通过setColorMode设置应用的颜色模式需要注意通过setColorMode改变模式,同样可以被this.context.config.colorMode以及onConfigurationOnUpdate监听

  • Web组件通过darkMode和forceDarkAccess属性,配置是否强制接入深色模式。

案例代码

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

@Entry
@Component
struct TogglePage2 {
  @State isDarkMode: boolean = false
  build() {
    Column() {
      Toggle({ type: ToggleType.Switch ,isOn:this.isDarkMode})//isOn 属性值在有触发刷新页面的场景中,不要省略
        .onChange((isOn: boolean) => {
          console.log('Toggle.onChange2: isOn', isOn)
          this.isDarkMode = isOn
          getContext(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 = true
 
  build() {
    Column() {
      Web({ src: 'www.xxx.com', controller: this.controller }).darkMode(this.mode).forceDarkAccess(this.access)
    }
  }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值