家人们,在鸿蒙应用开发的时候,主题的定制和管理对提升用户体验那可太重要啦!一个好看又风格统一的主题,不仅能让应用在视觉上超吸睛,还能让用户对应用更有认同感和归属感。而且不同的主题风格还能满足大家在各种场景下的个性化需求,像晚上用的时候,深色模式主题就能减少屏幕对眼睛的刺激,用起来更舒服。所以啊,怎么高效实现主题的定制和切换,就成了鸿蒙开发者特别关心的事儿。
今天就给大家好好介绍一款超实用的鸿蒙开发封装工具 —— 主题工具,有了它,开发者实现主题管理和切换就轻松多啦,开发效率能大大提高,开发成本也能降低。用了这个工具,开发者就能把更多精力放在应用的核心功能开发上,给用户打造出更优质的鸿蒙应用!
在鸿蒙开发里,主题工具就是专门用来管理和切换应用主题的类库或者模块。它把颜色、字体、样式这些界面元素统一抽象管理起来,给开发者提供了超便捷的方法,能轻松定制和切换应用主题。
主题工具的关键作用,就是把应用的外观设计和业务逻辑分开。这样开发者不用操心影响业务功能,就能轻轻松松修改和扩展应用主题。举个例子,开发者用主题工具,能快速把应用从亮色模式换成深色模式,也能根据不同节日、活动这些场景,给应用设置特定的主题风格。
而且呀,主题工具还能让代码更好维护、更好复用。把和主题有关的代码都封装在一个单独的工具类里,开发者就不用在好多页面和组件里重复写一样的主题设置代码了,代码复杂度一下子就降低了,开发效率也提高啦。另外,要是想修改应用主题,开发者只需要在主题工具类里改改就行,不用在整个应用里一个一个找相关代码再修改,代码维护起来方便多了。
主题工具提供了便捷的主题切换功能,支持亮色、暗色模式切换以及跟随系统模式 。在实现主题切换时,主要通过调用ApplicationContext.setColorMode方法来设置应用的颜色模式。
以亮色和暗色模式切换为例,代码示例如下:
/**
* 设置主题模式
* @param mode - 要设置的颜色模式,来自ConfigurationConstant.ColorMode枚举
* 功能:
* 1. 更新应用存储中的主题模式
* 2. 获取应用上下文同步系统颜色模式
* 3. 若存在有效上下文则更新系统级颜色配置
*/
setTheme(mode: ConfigurationConstant.ColorMode) {
// 更新应用存储 更新本地存储的颜色模式
AppStorage.setOrCreate<ConfigurationConstant.ColorMode>(ColorModeKey, mode)
// 同步到系统设置 设置系统的颜色模式
const ctx = AppStorage.get<Context>('context')
if (ctx) {
ctx.getApplicationContext().setColorMode(mode)
// 4. 存储当前的颜色模式是深色还是浅色
AppStorage.setOrCreate('isDark',
(ctx as common.UIAbilityContext).config.colorMode === ConfigurationConstant.ColorMode.COLOR_MODE_DARK)
}
}
/**
* 设置深色
* 无参数
* 无返回值
*/
setDark() {
this.setTheme(ConfigurationConstant.ColorMode.COLOR_MODE_DARK)
}
/**
* 设置浅色
* 无参数
* 无返回值
*/
setLight() {
this.setTheme(ConfigurationConstant.ColorMode.COLOR_MODE_LIGHT)
}
export const theme = new Theme();
// 使用时,切换到深色模式
theme.setDark();
// 切换到浅色模式
theme.setLight();
上述代码中,Theme
类封装了主题切换的相关方法。setDark
方法将主题设置为深色模式,setLight
方法将主题设置为亮色模式 。在setTheme
方法中,首先更新应用存储中的主题模式,然后获取应用上下文并同步系统颜色模式。
对于跟随系统模式,实现起来也非常简单,只需调用noSet
方法即可:
class Theme {
/**
* 设置系统跟随
* 无参数
* 无返回值
*/
noSet() {
this.setTheme(ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET)
}
// 其他方法...
}
// 使用时,设置跟随系统模式
theme.noSet();
通过这种方式,应用的主题模式将跟随系统的设置进行切换,无需开发者手动干预。
在主题工具中,资源管理是一项重要的功能。它主要负责管理主题相关的颜色、字体、图标等资源 ,确保在不同主题模式下,这些资源能够正确地被加载和使用。
以颜色资源为例,在项目的resources
目录下,可以通过创建不同的限定词目录来管理不同主题模式下的颜色资源。比如,创建base/element/color.json
文件用于存放亮色模式下的颜色配置,创建dark/element/color.json
文件用于存放暗色模式下的颜色配置 。在这两个文件中,可以定义同名的颜色资源,但赋予不同的色值。
例如:
base/element/color.json
文件内容:
{
"color": [
{
"name": "start_window_background",
"value": "#FFFFFF"
},
{
"name": "common_gray_01",
"value": "#979797"
},
{
"name": "common_gray_02",
"value": "#848484"
},
{
"name": "common_gray_03",
"value": "#666666"
},
{
"name": "common_gray_bg",
"value": "#f3f4f5"
},
{
"name": "common_gray_border",
"value": "#e8e7ee"
},
{
"name": "common_main_color",
"value": "#FA6D1D"
},
{
"name": "common_green",
"value": "#41B883"
},
{
"name": "common_blue",
"value": "#3266EE"
},
{
"name": "common_blue_bg",
"value": "#EDF2FF"
},
{
"name": "black",
"value": "#131313"
},
{
"name": "white",
"value": "#ffffff"
},
{
"name": "home_gray",
"value": "#EDECF2"
}
]
}
dark/element/color.json
文件内容:
{
"color": [
{
"name": "start_window_background",
"value": "#000000"
},
{
"name": "common_gray_01",
"value": "#979797"
},
{
"name": "common_gray_02",
"value": "#848484"
},
{
"name": "common_gray_03",
"value": "#666666"
},
{
"name": "common_gray_bg",
"value": "#232323"
},
{
"name": "common_gray_border",
"value": "#323232"
},
{
"name": "common_main_color",
"value": "#FA6D1D"
},
{
"name": "common_green",
"value": "#41B883"
},
{
"name": "common_blue",
"value": "#3266EE"
},
{
"name": "common_blue_bg",
"value": "#EDF2FF"
},
{
"name": "black",
"value": "#ffffff"
},
{
"name": "white",
"value": "#131313"
},
{
"name": "home_gray",
"value": "#b3b3cc"
}
]
}
在页面中调用颜色资源时,使用$r('app.color.app_title_color')
的方式,系统会根据当前的主题模式自动加载对应的颜色值 。
对于字体和图标资源,也可以采用类似的方式进行管理。通过在不同的限定词目录下放置不同主题模式下对应的字体文件和图标文件,在代码中使用统一的资源引用方式,实现资源的自动切换。
在应用启动时,通常需要初始化主题,以确保应用在整个生命周期内保持一致的主题风格 。以下是一个在应用启动时初始化主题的代码示例:
import { SettingsThemeDialog } from "../views/SettingsThemeDialog"
import { ConfigurationConstant } from "@kit.AbilityKit"
import { ColorModeKey } from "../commons/utils"
export interface Tool {
icon?: ResourceStr
name: string
value?: string
onClick?: () => void,
radius?: 0 | 1 | 2
}
@Entry
@Component
struct ThreePage {
// 获取本地存储的颜色模式
@StorageProp(ColorModeKey) colorMode: ConfigurationConstant.ColorMode =
ConfigurationConstant.ColorMode.COLOR_MODE_LIGHT
/**
* 自定义深色模式弹层
*/
dialog = new CustomDialogController({
builder: SettingsThemeDialog(),
alignment: DialogAlignment.Bottom
})
@Builder
toolsBuilder(tool: Tool) {
Row() {
if (tool.icon) {
Image(tool.icon)
.width(16)
.aspectRatio(1)
.margin({ right: 12 })
}
Text(tool.name)
.fontSize(16)
Blank()
if (tool.value) {
Text(tool.value)
.fontSize(14)
.fontColor($r('app.color.common_gray_01'))
.margin({ right: 10 })
}
Image($r('sys.media.ohos_ic_public_arrow_right'))
.width(18)
.aspectRatio(1)
.fillColor($r('app.color.common_gray_01'))
}
.height(50)
.width('100%')
.backgroundColor($r('app.color.white'))
.padding({ left: 16, right: 10 })
.borderRadius({
topLeft: tool.radius === 1 ? 8 : 0,
topRight: tool.radius === 1 ? 8 : 0,
bottomLeft: tool.radius === 2 ? 8 : 0,
bottomRight: tool.radius === 2 ? 8 : 0
})
.onClick(() => {
tool.onClick && tool.onClick()
})
}
build() {
Column() {
this.toolsBuilder({
name: '深色模式',
value: this.colorMode !== ConfigurationConstant.ColorMode.COLOR_MODE_DARK ? '已关闭' : '已开启',
radius: 1,
onClick: () => {
this.dialog.open()
}
})
}
.justifyContent(FlexAlign.Center)
.height('100%')
.width('100%')
}
}
在上述代码中,首先导入了主题工具theme
,然后在ThreePage
组件的toolsBuilder
方法中,调用theme.initTheme()
方法初始化主题,该方法会从本地存储中读取用户之前设置的主题模式,并应用到应用中 。接着,根据当前存储的颜色模式,调用相应的主题设置方法,实现全局主题的统一设置。
以前搞鸿蒙应用开发的时候,想切换主题可太麻烦啦!开发人员得在好多页面和组件里,手动去改颜色、字体这些样式属性。就拿一个有好多页面和超多组件的应用来说吧,要是想实现亮色和暗色模式切换,开发人员就得在每个页面的代码里,一个一个地找相关样式代码然后修改,这活儿又繁琐又费时间,还特别容易出错。
但是用了主题工具就不一样啦!开发人员只要在主题工具类里,把不同主题的样式资源定义好,然后调用主题工具的切换方法,整个应用的主题就切换成功啦!就像之前介绍的那个主题工具,开发人员只要调用theme.setDark()
或者theme.setLight()
方法,亮色和暗色主题就能轻松切换,根本不用在每个页面和组件里重复写切换逻辑,重复代码的编写量大大减少,开发效率自然就提高啦!
根据实际项目经验统计,用了主题工具之后,开发主题相关功能的时间,比以前传统方式缩短了差不多 50%,开发效率提升可明显啦!
主题工具能满足用户在不同场景下的个性化需求,让用户用起应用来更舒服、更方便。比如说,晚上用应用的时候,用户切换到深色模式主题,屏幕对眼睛的刺激就会小很多,能保护视力呢。而且不同的主题风格,用户还能按照自己的喜好和心情,把应用界面设置成自己喜欢的样子,这样用户对应用就更有认同感和归属感啦。
从用户反馈的数据来看,应用里加上主题切换功能之后,用户满意度提高了大概 30% 呢。好多用户都说,有了主题切换功能,他们能按照不同使用场景和个人喜好,自由选择应用的主题风格,应用的使用体验提升了好多。有个用户在反馈里就说:“这个应用的主题切换功能太赞了,晚上我能切换到深色模式,眼睛看着特舒服,不同主题风格还让我手机界面更个性了,我可喜欢了。”
没使用主题工具的时候,应用里和主题相关的代码,可能分散在各个页面和组件里,代码结构乱糟糟的,维护起来特别费劲。要是想修改主题样式,或者添加新主题,开发人员就得在整个项目里到处找相关代码然后修改,这效率低不说,还特别容易遗漏,一不小心就会出现兼容性问题。
但是用了主题工具就好多啦,主题相关的代码都封装在一个独立的类里,代码结构看着可清楚了,维护起来也轻松。要是需要更新主题或者添加新主题,开发人员只要在主题工具类里改就行,不用在整个应用里一个一个找代码修改。比如说,想修改应用暗色主题的颜色,开发人员在主题工具类里修改暗色主题的颜色资源配置,应用里所有用这个主题的页面和组件就会自动更新,代码的可维护性大大提高。
对比一下使用主题工具前后的代码结构,就能明显发现,用了主题工具之后,代码结构更简洁、更清晰,主题相关的代码都集中在主题工具类里,管理和维护都方便多了。
import { common, ConfigurationConstant } from "@kit.AbilityKit"
export const ColorModeKey = 'interview-color-mode'
class Theme {
/**
* 初始化(持久化)
* 功能:初始化主题配置并持久化存储
* 1. 将浅色模式作为默认值持久化存储
* 2. 从应用存储中获取当前主题模式并应用
* 无参数
* 无返回值
*/
initTheme() {
// 设置默认颜色模式并持久化 1. 持久化到本地(没有则创建, 有则无变化)
PersistentStorage.persistProp(ColorModeKey, ConfigurationConstant.ColorMode.COLOR_MODE_LIGHT)
// 获取并应用当前存储的主题模式 2. 从本地读取颜色模式
const colorMode = AppStorage.get<ConfigurationConstant.ColorMode>(ColorModeKey)
// 3. 存到本地 和 设置颜色模式
this.setTheme(colorMode!)
}
/**
* 设置主题模式
* @param mode - 要设置的颜色模式,来自ConfigurationConstant.ColorMode枚举
* 功能:
* 1. 更新应用存储中的主题模式
* 2. 获取应用上下文同步系统颜色模式
* 3. 若存在有效上下文则更新系统级颜色配置
*/
setTheme(mode: ConfigurationConstant.ColorMode) {
// 更新应用存储 更新本地存储的颜色模式
AppStorage.setOrCreate<ConfigurationConstant.ColorMode>(ColorModeKey, mode)
// 同步到系统设置 设置系统的颜色模式
const ctx = AppStorage.get<Context>('context')
if (ctx) {
ctx.getApplicationContext().setColorMode(mode)
// 4. 存储当前的颜色模式是深色还是浅色
AppStorage.setOrCreate('isDark',
(ctx as common.UIAbilityContext).config.colorMode === ConfigurationConstant.ColorMode.COLOR_MODE_DARK)
}
}
/**
* 设置系统跟随
* 无参数
* 无返回值
*/
noSet() {
this.setTheme(ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET)
}
/**
* 设置深色
* 无参数
* 无返回值
*/
setDark() {
this.setTheme(ConfigurationConstant.ColorMode.COLOR_MODE_DARK)
}
/**
* 设置浅色
* 无参数
* 无返回值
*/
setLight() {
this.setTheme(ConfigurationConstant.ColorMode.COLOR_MODE_LIGHT)
}
}
export const theme = new Theme()
上述代码中,theme
是主题工具的实例,通过调用initTheme
方法,完成主题的初始化配置,包括从本地存储中读取用户之前设置的主题模式,并应用到应用中 。
配置主题资源是使用主题工具的关键步骤,它决定了应用在不同主题模式下的外观展示 。
创建主题资源文件:在项目的resources
目录下,创建base/element/color.json
文件用于存放亮色模式下的颜色资源,创建dark/element/color.json
文件用于存放暗色模式下的颜色资源 。如果需要添加自定义主题模式,可创建对应的目录和资源文件 。
配置颜色资源:在color.json
文件中,定义主题所需的颜色资源 。例如,在base/element/color.json
中:
{
"color": [
{
"name": "start_window_background",
"value": "#FFFFFF"
},
{
"name": "common_gray_01",
"value": "#979797"
},
{
"name": "common_gray_02",
"value": "#848484"
},
{
"name": "common_gray_03",
"value": "#666666"
},
{
"name": "common_gray_bg",
"value": "#f3f4f5"
},
{
"name": "common_gray_border",
"value": "#e8e7ee"
},
{
"name": "common_main_color",
"value": "#FA6D1D"
},
{
"name": "common_green",
"value": "#41B883"
},
{
"name": "common_blue",
"value": "#3266EE"
},
{
"name": "common_blue_bg",
"value": "#EDF2FF"
},
{
"name": "black",
"value": "#131313"
},
{
"name": "white",
"value": "#ffffff"
},
{
"name": "home_gray",
"value": "#EDECF2"
}
]
}
在dark/element/color.json
中:
{
"color": [
{
"name": "start_window_background",
"value": "#000000"
},
{
"name": "common_gray_01",
"value": "#979797"
},
{
"name": "common_gray_02",
"value": "#848484"
},
{
"name": "common_gray_03",
"value": "#666666"
},
{
"name": "common_gray_bg",
"value": "#232323"
},
{
"name": "common_gray_border",
"value": "#323232"
},
{
"name": "common_main_color",
"value": "#FA6D1D"
},
{
"name": "common_green",
"value": "#41B883"
},
{
"name": "common_blue",
"value": "#3266EE"
},
{
"name": "common_blue_bg",
"value": "#EDF2FF"
},
{
"name": "black",
"value": "#ffffff"
},
{
"name": "white",
"value": "#131313"
},
{
"name": "home_gray",
"value": "#b3b3cc"
}
]
}
配置其他资源:除了颜色资源,还可以配置字体、图标等其他资源 。例如,在resources/base/font
目录下存放亮色模式下的字体文件,在resources/dark/font
目录下存放暗色模式下的字体文件 。在配置图标资源时,同样可以通过在不同的限定词目录下放置不同主题模式对应的图标文件,实现图标资源的自动切换。
在完成主题工具的引入和主题资源的配置后,就可以在页面中应用主题了 。
弹窗控制器:在需要应用弹窗的页面文件中,导入弹窗控制器 。例如:
/**
* 自定义深色模式弹层
*/
dialog = new CustomDialogController({
builder: SettingsThemeDialog(),
alignment: DialogAlignment.Bottom
})
自定义弹窗界面:在自定义弹窗中builder
需要导入弹窗样式。例如:
import { ColorModeKey, theme } from "../commons/utils"
import { ConfigurationConstant } from "@kit.AbilityKit"
@CustomDialog
export struct SettingsThemeDialog {
controller: CustomDialogController
// 获取本地存储的颜色模式
@StorageProp(ColorModeKey) colorMode: ConfigurationConstant.ColorMode =
ConfigurationConstant.ColorMode.COLOR_MODE_LIGHT
build() {
Column() {
Row() {
Column({ space: 4 }) {
Text('跟随系统')
Text('开启后,将跟随系统打开或关闭深色模式')
.fontSize(12)
.fontColor($r('app.color.common_gray_01'))
}
.alignItems(HorizontalAlign.Start)
Toggle({
type: ToggleType.Switch,
isOn: this.colorMode === ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET // 是否跟随系统模式
})
.onChange((val) => {
if (val) {
theme.noSet()
} else {
theme.setLight()
}
})
}
.width('100%')
.height(70)
.justifyContent(FlexAlign.SpaceBetween)
.border({ width: { bottom: 0.5 }, color: $r('app.color.common_gray_border') })
if (this.colorMode !== ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET) {
Row() {
Text('普通模式')
.fontSize(15)
Blank()
if (this.colorMode === ConfigurationConstant.ColorMode.COLOR_MODE_LIGHT) {
Image($r('app.media.ic_public_ok'))
.width(16)
.aspectRatio(1)
.fillColor($r('app.color.common_green'))
}
}
.width('100%')
.height(50)
.border({ width: { bottom: 0.5 }, color: $r('app.color.common_gray_border') })
.onClick(() => {
theme.setLight()
})
Row() {
Text('深色模式')
.fontSize(15)
Blank()
if (this.colorMode === ConfigurationConstant.ColorMode.COLOR_MODE_DARK) {
Image($r('app.media.ic_public_ok'))
.width(16)
.aspectRatio(1)
.fillColor($r('app.color.common_green'))
}
}
.width('100%')
.height(50)
.onClick(() => {
theme.setDark()
})
}
}
.padding({
top: 15,
bottom: 15,
left: 30,
right: 30
})
.backgroundColor($r('app.color.white'))
}
}
主页面:在页面中添加主题切换的交互逻辑,例如通过按钮点击事件来切换主题 。示例代码如下:
import { SettingsThemeDialog } from "../views/SettingsThemeDialog"
import { ConfigurationConstant } from "@kit.AbilityKit"
import { ColorModeKey } from "../commons/utils"
export interface Tool {
icon?: ResourceStr
name: string
value?: string
onClick?: () => void,
radius?: 0 | 1 | 2
}
@Entry
@Component
struct ThreePage {
// 获取本地存储的颜色模式
@StorageProp(ColorModeKey) colorMode: ConfigurationConstant.ColorMode =
ConfigurationConstant.ColorMode.COLOR_MODE_LIGHT
/**
* 自定义深色模式弹层
*/
dialog = new CustomDialogController({
builder: SettingsThemeDialog(),
alignment: DialogAlignment.Bottom
})
@Builder
toolsBuilder(tool: Tool) {
Row() {
if (tool.icon) {
Image(tool.icon)
.width(16)
.aspectRatio(1)
.margin({ right: 12 })
}
Text(tool.name)
.fontSize(16)
Blank()
if (tool.value) {
Text(tool.value)
.fontSize(14)
.fontColor($r('app.color.common_gray_01'))
.margin({ right: 10 })
}
Image($r('sys.media.ohos_ic_public_arrow_right'))
.width(18)
.aspectRatio(1)
.fillColor($r('app.color.common_gray_01'))
}
.height(50)
.width('100%')
.backgroundColor($r('app.color.white'))
.padding({ left: 16, right: 10 })
.borderRadius({
topLeft: tool.radius === 1 ? 8 : 0,
topRight: tool.radius === 1 ? 8 : 0,
bottomLeft: tool.radius === 2 ? 8 : 0,
bottomRight: tool.radius === 2 ? 8 : 0
})
.onClick(() => {
tool.onClick && tool.onClick()
})
}
build() {
Column() {
this.toolsBuilder({
name: '深色模式',
value: this.colorMode !== ConfigurationConstant.ColorMode.COLOR_MODE_DARK ? '已关闭' : '已开启',
radius: 1,
onClick: () => {
this.dialog.open()
}
})
}
.justifyContent(FlexAlign.Center)
.height('100%')
.width('100%')
}
}
通过以上步骤,就可以在页面中成功应用主题工具,实现主题的切换和展示 。
家人们,今天给大家唠唠鸿蒙开发封装工具里的主题工具,这玩意儿功能可太丰富啦!它切换主题超方便,亮色、暗色模式随意切换,还能跟随系统模式,不管啥场景,都能满足咱个性化的需求。而且,它管理资源也很有一套,颜色、字体、图标这些主题资源,都能统一管理,加载起来也灵活。更厉害的是,它还有超强大的自定义扩展功能,开发者可以根据项目需要,定制出独一无二的主题风格,简直绝绝子!
在使用场景这块儿,主题工具可牛啦!它既能用在整个应用的主题设置上,保证应用从开始到结束,主题风格都始终如一;又能对局部页面的主题进行定制,满足特定页面那些特别的主题需求。
从优势亮点来说,主题工具大大提高了开发效率,写主题相关代码的工作量少了好多。它还优化了用户体验,有各种各样的主题可以选,还能个性化定制,让用户对应用更有认同感和归属感。同时呢,代码的可维护性也变强了,主题相关代码的结构更清晰,管理和更新都更方便。
未来呀,主题工具肯定能往更智能的方向发展。就好比,用上人工智能技术之后,它能根据咱们的使用习惯和场景,自动推荐超合适的主题。要是晚上经常用某个应用,它就自动推荐暗色模式主题;要是在阅读类应用里长时间看书,它还能根据阅读时长和光线条件,智能调节主题的亮度和对比度,让阅读体验超舒适。
在功能拓展这块,以后能支持更多类型的主题资源,像动画效果、声音效果啥的。开发者可以给不同主题加些独特的动画过渡效果,这样主题切换起来就特别流畅自然,视觉感受一下子就提升啦;也可以给主题配上相应的声音效果,比如切换到节日主题的时候,就播放欢快的节日音乐,节日氛围直接拉满。
还有哦,随着鸿蒙生态不停地发展,主题工具肯定得更好地适配各种设备和平台。不管是手机、平板、智能手表还是智慧屏这些鸿蒙设备,都能轻松实现主题的无缝切换,展示效果也都一样,给大家带来超统一的全场景体验。