Harmonyos之深浅模式适配

news2024/12/15 6:43:31

Harmonyos之换肤功能

  • 概述
  • 实现原理
  • 颜色适配
    • 颜色资源配置
    • 工具类编写
    • 界面代码编写
    • 适配效果

概述

深色模式(Dark Mode)又称之为暗色模式,是与日常应用使用过程中的浅色模式(Light Mode)相对应的一种UI主题。

换肤功能应该是现在APP常见的一个功能, 现在我们来了解下载Harmonyos上app是如何实现换肤功能的。

实现原理

当系统切换到深色模式后,应用内可能会出现部分内容切换到深色主题的情况,例如状态栏、弹窗背景色、系统控件等,会导致应用内页面效果错乱。

为应对上述情况,需要对应用进行深色模式下的内容适配,目前该适配主要依靠资源目录。当系统对应的设置项发生变化后(如系统语言、深浅色模式等),应用会自动加载对应资源目录下的资源文件。

创建的项目默认是支持浅色模式的, 资源一般都放在src/main/resources/base目录下的,如下图:
在这里插入图片描述
但是系统为深色模式预留了dark目录,该目录在应用创建时默认不存在,在进行深色模式适配时,需要开发者在src/main/resources中手动地创建出dark目录,将深色模式所需的资源放置到该目录下。
在这里插入图片描述

说明
在进行资源定义时,需要在base目录与dark目录中定义同名的资源。例如在base/element/color.json文件中定义text_color为黑色,在dark/element/color.json文件中定义text_color为白色,那么当深浅色切换时,应用内使用了$('app.color.text_color ')作为颜色值的元素会自动切换到对应的颜色,而无需使用其他逻辑判断进行控制。

颜色适配

颜色资源配置

对于颜色资源的适配, 目前有两种方式:

  • 使用系统资源, 当系统切换模式时, 使用受支持的系统资源会自动适配深浅模式。开发人员可以查看支持的系统资源
  • 使用自定义的主题,那么就需要配置不同主题的颜色资源。

这里以配置自定义主题来适配颜色:

配置浅色模式的颜色资源, 配置目录src/main/resources/base/element/color.json

{
  "color": [
  // 浅色主题的颜色
    {
      "name": "test_skin",
      "value": "#008000"
    }
  ]
}

配置深色模式, 配置目录src/main/resources/dark/element/color.json

{
  "color": [
   // 深色主题颜色
    {
      "name": "test_skin",
      "value": "#FFFF00"
    }
  ]
}

工具类编写

AppSkinManager工具类的编写:

import { appPreferences } from './AppPreferences'
import { ConfigurationConstant } from '@kit.AbilityKit';
import { window } from '@kit.ArkUI';
import { BusinessError } from '@ohos.base';
import { JSON } from '@kit.ArkTS';

const TAG = "AppSkinManager"
export enum AppSkinMode {
  // 未设置  跟随系统
  NOT_SET,

  // 白色
  LIGHT,

  // 黑色
  DARK
}

export class AppSkinManager {
  // 当前皮肤色, 默认没有设置
  skinMode: AppSkinMode = AppSkinMode.NOT_SET;
  private SKIN_KEY: string = 'skinMode'

  // 判断当前是否是黑板
  static isDartMode(mode: AppSkinMode) {
    return mode === AppSkinMode.DARK;
  }

  // 初始化方法
  public init() {
    // 初始化黑白版
    this.skinMode = appPreferences.getSync(this.SKIN_KEY, AppSkinMode.NOT_SET) as number;
    console.log(`shinMode get from file is ${this.skinMode}`);
  }

  // 更换皮肤
  public changeSkin(context: Context, mode: AppSkinMode) {
    if (this.skinMode !== mode) {
      this.skinMode = mode;
      appPreferences.putSync(this.SKIN_KEY, mode.valueOf());
    }
    console.log(`skin save to PersistentStorage ${appPreferences.getSync('skinMode', AppSkinMode.NOT_SET)}`);

    if (AppSkinManager.isDartMode(mode)) {
      // 设置应用的颜色模式为 深色
      context.getApplicationContext().setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_DARK)
    } else {
      context.getApplicationContext().setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_LIGHT);
    }

    // 改变系统导航栏、状态栏的颜色
    this.changeSystemBar(context, mode)
  }

  changeSystemBar(context: Context, mode: AppSkinMode) {
    let statusBarColor = AppSkinManager.getSystemBarColorByMode(mode)
    let statusBarTextColor = AppSkinManager.getSystemBarTextColorByMode(mode)
    this.setSystemBarColor(context, statusBarColor, statusBarTextColor)
  }

  // 根据当前的颜色模式,获取当前系统bar的颜色
  static getSystemBarColorByMode(mode: AppSkinMode) {
    if (AppSkinManager.isDartMode(mode)) {
      return '#000000';
    }
    return '#FFFFFF';
  }

  // 根据当前的颜色模式, 获取当前系统bar文本的颜色
  static getSystemBarTextColorByMode(mode: AppSkinMode) {
    if (AppSkinManager.isDartMode(mode)) {
      return '#FFFFFF';
    }
    return '#000000';
  }

  // 设置主窗口全屏模式时窗口内导航栏、状态栏的属性
  setSystemBarColor(context: Context, statusBarColor: string, statusBarTextColor: string) {
    try {
      // 首先是获取应用的主窗口
      let windowsClass: window.Window | null = null;
      // 获取当前应用内最上层的子窗口,若无应用子窗口,则返回应用主窗口
      window.getLastWindow(context, (err, data) => {
        if (err.code) {
          return
        }
        windowsClass = data

        //创建属性
        let systemBarProperties: window.SystemBarProperties = {
          statusBarColor: statusBarColor,
          statusBarContentColor: statusBarTextColor,
          navigationBarColor: statusBarColor
        }
        // 设置窗口的属性
        windowsClass.setWindowSystemBarProperties(systemBarProperties, (err: BusinessError) => {
          if (err.code) {
            return;
          }
        })
      })
    } catch (exception) {
      console.error(TAG, "setSystemBarColor:" + JSON.stringify(exception))
    }
  }
}

界面代码编写

//Index.ets主页面代码 
@Entry
@Component
struct Index {
  build() {
    Column(){
      ChangeSkinView()
        .width('100%')
        .height('50%')
        .margin({ top: 100})
      Text("验证换肤功能是否正常")
        .fontSize(50)
        .fontColor($r('app.color.test_skin'))
    }
  }
}

//切换换肤的组件
@Component
export struct ChangeSkinView {
  build() {
    Column(){
      Button("简约白").onClick((event: ClickEvent) => {
        // 切换到白班
        changeSkin(AppSkinMode.LIGHT)
      })
      Button("尊贵黑").onClick((event: ClickEvent) => {
        // 切换到黑板
        changeSkin(AppSkinMode.DARK)
      })
    }
  }
}

适配效果

浅色效果:
在这里插入图片描述

深色效果:
在这里插入图片描述

除了上述的颜色资源适配外, 还有媒体资源适配和web页面适配, 开发人员可以参考官方文档。

官方文档:https://developer.huawei.com/consumer/cn/doc/best-practices-V5/bpta-dark-mode-adaptation-V5#section128661451172714

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2259796.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

蓝桥杯刷题——day4

蓝桥杯刷题——day4 题目一题干题目解析代码 题目二题干题目解析代码 题目一 题干 小蓝和朋友们在玩一个报数游戏。由于今年是2024 年,他们决定要从小到大轮流报出是20或24倍数的正整数。前10个被报出的数是:20,24,40,48,60,72,80,96,100,120。请问第2…

Git:常用命令

一、查看当前分支 git branch 二、查看所有分支 git branch -a 三、切换到远程分支 git checkout origin/分支名 示例:git checkout origin/dev 四、拉取远程分支代码 git pull origin 分支名 示例:git pull origin dev 五、常用指令 查看暂存区…

算法题(4):报数游戏

审题:首先这题本质上是数学题中的找规律问题,我们需要用到编程的地方也只是辅助计算 思路:首先先用枚举法多算几个数出来,然后观察规律 枚举之后我们发现从第一个位置开始每过十个数就会增加120,所以每十个数可以算一个…

短视频矩阵源码开发部署全流程解析

在当今的数字化时代,短视频已成为人们娱乐、学习和社交的重要方式。短视频矩阵系统的开发与部署,对于希望在这一领域脱颖而出的企业和个人而言,至关重要。本文将详细阐述短视频矩阵源码的开发与部署流程,并附上部分源代码示例&…

【FLASH、SRAM和DRAM、CISC和RISC、冯诺依曼和哈佛】单片机内存结构的了解

【FLASH、SRAM和DRAM、CISC和RISC、冯诺依曼和哈佛】单片机内存结构的了解 一、单片机概念 单片机:Single-Chip Microcomputer,单片微型计算机,是一种集成电路芯片 1.1RAM里的SRAM和DRAM SRAM(Static Random Access Memory&…

STM32仿真——01创建工程

目录 1.需要用到的软件工具​编辑 2.第一步Proteus软件新建工程​编辑 3.第二步——stm32cubumx 4、MDK代码编写 #注意安装的过程或者使用过程使用英文,以防报错; 1.需要用到的软件工具 2.第一步Proteus软件新建工程 选中,默认 先布局&…

Spark3.2.0集群部署ON YARN

环境说明 准备三台服务器,分别为:bigdata141(hadoop 主节点)、bigdata142、bigdata143确保 hadoop 集群先启动好,我这边的 hadoop 版本为 3.2.0另准备一台服务器,bigdata144,作为 hadoop 客户端…

GLM-4-Plus初体验

引言:为什么高效的内容创作如此重要? 在当前竞争激烈的市场环境中,内容创作已成为品牌成功的重要支柱。无论是撰写营销文案、博客文章、社交媒体帖子,还是制作广告,优质的内容不仅能够帮助品牌吸引目标受众的注意力&a…

C++获取时间戳/计算运行时长

一、便于使用&#xff0c;使用chrono封装一个简单的类 #pragma once#include <chrono>using CTime_point std::chrono::high_resolution_clock::time_point;class CElapsedTime final { public:static CTime_point now() {return std::chrono::high_resolution_clock::…

IDEA方法注释模板设置

目录 创建模板 新建模板&#xff1a;命名为* 设置模板内容-IDEA格式模板 设置模板应用场景 设置参数 创建模板 /**Enter这里我们也按照这种习惯来设置IDEA的方法注释&#xff1a;File-->Settings-->Editor-->Live Templates 先新建模板组&#xff0c;然后在模板组中…

Xcode

info.plist Appearance Light 关闭黑暗模式 Bundle display name 设置app名称&#xff0c;默认为工程名 Location When In Use Usage Description 定位权限一共有3个key 1.Privacy - Location When In Use Usage Description 2.Privacy - Location Always and When In U…

探索 Cesium 的未来:3D Tiles Next 标准解析

探索 Cesium 的未来&#xff1a;3D Tiles Next 标准解析 随着地理信息系统&#xff08;GIS&#xff09;和 3D 空间数据的快速发展&#xff0c;Cesium 作为领先的开源 3D 地球可视化平台&#xff0c;已成为展示大规模三维数据和进行实时渲染的强大工具。近年来&#xff0c;随着…

掘金电影市场的新机遇:开发特惠电影票小程序api文档

随着电影市场的不断扩大&#xff0c;特惠电影票小程序成为创业者和企业争相布局的新蓝海。本文将带你深入了解特惠电影票小程序的开发要点&#xff0c;以及如何通过这个项目实现盈利。 项目背景及市场分析 电影市场规模的不断扩大为特惠电影票小程序提供了广阔的市场空间。 根…

JaxaFx学习(一)

目录&#xff1a; &#xff08;1&#xff09;基本结构 &#xff08;2&#xff09;Application &#xff08;3&#xff09;Stage窗口显示 &#xff08;4&#xff09;Scene场景切换 &#xff08;5&#xff09;UI控件通用属性 &#xff08;6&#xff09;UI控件属性绑定很属性…

java抽奖系统(七)

8. 抽奖活动 8.1 新建抽奖活动 创建的活动信息包含&#xff1a; i. 活动名称 ii. 活动描述 iii. 圈选奖品&#xff1a;勾选对应奖品&#xff0c;并设置奖品等级&#xff08;⼀⼆三等奖&#xff09;&#xff0c;及奖品数量 iv. 圈选⼈员&#xff1a;勾选参与抽奖⼈员 库表关联…

Unity学习笔记(一)如何实现物体之间碰撞

前言 本文为Udemy课程The Ultimate Guide to Creating an RPG Game in Unity学习笔记 如何实现物体之间碰撞 实现物体之间的碰撞关键组件&#xff1a;Rigidbody 2D(刚体)、Collider 2D(碰撞体)、Sprite Renderer&#xff08;Sprite渲染器&#xff09; 实现物体之间的碰撞 …

MATLAB 平面直线与直线求交(99)

MATLAB 平面直线与直线求交(99) 一、算法介绍二、算法实现1.代码2.结果一、算法介绍 平面上,给定两直线,直线由两个点确定,计算直线与直线的交点,理论上只要不平行就有交点,下面是计算代码和效果: 二、算法实现 1.代码 代码如下(示例): % 示例用法 % 定义两条线…

STM32单片机芯片与内部21 电源管理——低功耗 睡眠模式 停止模式 待机模式

目录 一、SMT32电源框图 1、ADC电源与参考电压VDDA 2、调压器供电电路VDD/1.8V 3、备份域电路 二、电源监控器 1、上电复位与掉电复位&#xff08;POR与PDR&#xff09; 2、可编程电压检测器 PVD 三、功耗模式 1、睡眠模式 2、停止模式 3、待机模式 电源对电子设备的…

数智读书笔记系列006 协同进化:人类与机器融合的未来

书名:协同进化&#xff1a;人类与机器融合的未来 作者:[美]爱德华阿什福德李 译者:李杨 出版时间:2022-06-01 ISBN:9787521741476 中信出版集团制作发行 爱德华・阿什福德・李&#xff08;Edward Ashford Lee&#xff09;是一位在计算机科学与工程领域颇具影响力的学者&am…

计算机网络知识点全梳理(一.TCP/IP网络模型)

目录 TCP/IP网络模型概述 应用层 什么是应用层 应用层功能 应用层协议 传输层 什么是传输层 传输层功能 传输层协议 网络层 什么是网络层 网络层功能 网络层协议 数据链路层 什么是数据链路层 数据链路层功能 物理层 物理层的概念和功能 TCP/IP网络模型概述…