網(wǎng)站的手機站頁面重復(fù)新聞源軟文發(fā)布平臺
Harmonyos之換膚功能
- 概述
- 實現(xiàn)原理
- 顏色適配
- 顏色資源配置
- 工具類編寫
- 界面代碼編寫
- 適配效果
概述
深色模式(Dark Mode)又稱之為暗色模式,是與日常應(yīng)用使用過程中的淺色模式(Light Mode)相對應(yīng)的一種UI主題。
換膚功能應(yīng)該是現(xiàn)在APP常見的一個功能, 現(xiàn)在我們來了解下載Harmonyos上app是如何實現(xiàn)換膚功能的。
實現(xiàn)原理
當(dāng)系統(tǒng)切換到深色模式后,應(yīng)用內(nèi)可能會出現(xiàn)部分內(nèi)容切換到深色主題的情況,例如狀態(tài)欄、彈窗背景色、系統(tǒng)控件等,會導(dǎo)致應(yīng)用內(nèi)頁面效果錯亂。
為應(yīng)對上述情況,需要對應(yīng)用進行深色模式下的內(nèi)容適配,目前該適配主要依靠資源目錄。當(dāng)系統(tǒng)對應(yīng)的設(shè)置項發(fā)生變化后(如系統(tǒng)語言、深淺色模式等),應(yīng)用會自動加載對應(yīng)資源目錄下的資源文件。
創(chuàng)建的項目默認(rèn)是支持淺色模式的, 資源一般都放在src/main/resources/base
目錄下的,如下圖:
但是系統(tǒng)為深色模式預(yù)留了dark目錄,該目錄在應(yīng)用創(chuàng)建時默認(rèn)不存在,在進行深色模式適配時,需要開發(fā)者在src/main/resources
中手動地創(chuàng)建出dark
目錄,將深色模式所需的資源放置到該目錄下。
說明
在進行資源定義時,需要在base
目錄與dark
目錄中定義同名的資源。例如在base/element/color.json
文件中定義text_color
為黑色,在dark/element/color.json
文件中定義text_color
為白色,那么當(dāng)深淺色切換時,應(yīng)用內(nèi)使用了$('app.color.text_color ')
作為顏色值的元素會自動切換到對應(yīng)的顏色,而無需使用其他邏輯判斷進行控制。
顏色適配
顏色資源配置
對于顏色資源的適配, 目前有兩種方式:
- 使用系統(tǒng)資源, 當(dāng)系統(tǒng)切換模式時, 使用受支持的系統(tǒng)資源會自動適配深淺模式。開發(fā)人員可以查看支持的系統(tǒng)資源
- 使用自定義的主題,那么就需要配置不同主題的顏色資源。
這里以配置自定義主題來適配顏色:
配置淺色模式的顏色資源, 配置目錄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 {// 未設(shè)置 跟隨系統(tǒng)NOT_SET,// 白色LIGHT,// 黑色DARK
}export class AppSkinManager {// 當(dāng)前皮膚色, 默認(rèn)沒有設(shè)置skinMode: AppSkinMode = AppSkinMode.NOT_SET;private SKIN_KEY: string = 'skinMode'// 判斷當(dāng)前是否是黑板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)) {// 設(shè)置應(yīng)用的顏色模式為 深色context.getApplicationContext().setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_DARK)} else {context.getApplicationContext().setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_LIGHT);}// 改變系統(tǒng)導(dǎo)航欄、狀態(tài)欄的顏色this.changeSystemBar(context, mode)}changeSystemBar(context: Context, mode: AppSkinMode) {let statusBarColor = AppSkinManager.getSystemBarColorByMode(mode)let statusBarTextColor = AppSkinManager.getSystemBarTextColorByMode(mode)this.setSystemBarColor(context, statusBarColor, statusBarTextColor)}// 根據(jù)當(dāng)前的顏色模式,獲取當(dāng)前系統(tǒng)bar的顏色static getSystemBarColorByMode(mode: AppSkinMode) {if (AppSkinManager.isDartMode(mode)) {return '#000000';}return '#FFFFFF';}// 根據(jù)當(dāng)前的顏色模式, 獲取當(dāng)前系統(tǒng)bar文本的顏色static getSystemBarTextColorByMode(mode: AppSkinMode) {if (AppSkinManager.isDartMode(mode)) {return '#FFFFFF';}return '#000000';}// 設(shè)置主窗口全屏模式時窗口內(nèi)導(dǎo)航欄、狀態(tài)欄的屬性setSystemBarColor(context: Context, statusBarColor: string, statusBarTextColor: string) {try {// 首先是獲取應(yīng)用的主窗口let windowsClass: window.Window | null = null;// 獲取當(dāng)前應(yīng)用內(nèi)最上層的子窗口,若無應(yīng)用子窗口,則返回應(yīng)用主窗口window.getLastWindow(context, (err, data) => {if (err.code) {return}windowsClass = data//創(chuàng)建屬性let systemBarProperties: window.SystemBarProperties = {statusBarColor: statusBarColor,statusBarContentColor: statusBarTextColor,navigationBarColor: statusBarColor}// 設(shè)置窗口的屬性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頁面適配, 開發(fā)人員可以參考官方文檔。
官方文檔:https://developer.huawei.com/consumer/cn/doc/best-practices-V5/bpta-dark-mode-adaptation-V5#section128661451172714