HarmonyOS 鸿蒙Next主题管理深色模式如何实现切换?暗黑模式适配指南
HarmonyOS 鸿蒙Next主题管理深色模式如何实现切换?暗黑模式适配指南 harmonyOS 5.0,DevEco Studio 5.0
- 需要实现应用的深色/浅色主题切换功能
- 不清楚如何监听系统主题变化
- 希望了解颜色资源的正确配置方式
希望了解HarmonyOS主题管理的完整实现方案,包括颜色资源配置、主题切换和系统主题监听
1. 颜色资源配置
在 resources/base/element/color.json 中定义浅色主题颜色:
{
"color": [
{ "name": "primary", "value": "#36e27b" },
{ "name": "background", "value": "#f6f8f7" },
{ "name": "surface", "value": "#ffffff" },
{ "name": "text_primary", "value": "#111714" },
{ "name": "text_secondary", "value": "#6b7280" },
{ "name": "divider", "value": "#e5e7eb" }
]
}
在 resources/dark/element/color.json 中定义深色主题颜色:
{
"color": [
{ "name": "primary", "value": "#36e27b" },
{ "name": "background", "value": "#112117" },
{ "name": "surface", "value": "#1C2E24" },
{ "name": "text_primary", "value": "#ffffff" },
{ "name": "text_secondary", "value": "#9eb7a8" },
{ "name": "divider", "value": "#1a3d2a" }
]
}
2. 主题管理服务
3. 在EntryAbility中监听系统主题
// EntryAbility.ets
import { AbilityConstant, ConfigurationConstant, UIAbility, Want } from '@kit.AbilityKit'
import { ThemeManager } from '../utils/ThemeManager'
export default class EntryAbility extends UIAbility {
async onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): Promise<void> {
// 初始化主题管理器
await ThemeManager.getInstance().init(this.context)
// 获取当前系统主题
const colorMode = this.context.config.colorMode
ThemeManager.getInstance().updateSystemColorMode(colorMode)
}
// 监听系统配置变化
onConfigurationUpdate(newConfig: Configuration): void {
if (newConfig.colorMode !== undefined) {
ThemeManager.getInstance().updateSystemColorMode(newConfig.colorMode)
}
}
}
4. 主题设置页面
import { ThemeManager, ThemeMode } from '../utils/ThemeManager'
@Entry
@Component
struct ThemeSettingsPage {
@State currentMode: ThemeMode = ThemeMode.SYSTEM
@State isDark: boolean = false
private themeManager = ThemeManager.getInstance()
aboutToAppear(): void {
this.currentMode = this.themeManager.getThemeMode()
this.isDark = this.themeManager.isDarkMode()
// 监听主题变化
this.themeManager.addListener((isDark) => {
this.isDark = isDark
})
}
build() {
Column({ space: 16 }) {
Text('主题设置')
.fontSize(20)
.fontWeight(FontWeight.Bold)
.fontColor($r('app.color.text_primary'))
.width('100%')
// 主题选项
Column({ space: 8 }) {
this.ThemeOption('跟随系统', ThemeMode.SYSTEM)
this.ThemeOption('浅色模式', ThemeMode.LIGHT)
this.ThemeOption('深色模式', ThemeMode.DARK)
}
.padding(16)
.backgroundColor($r('app.color.surface'))
.borderRadius(16)
// 当前状态预览
Column({ space: 8 }) {
Text('当前状态')
.fontSize(14)
.fontColor($r('app.color.text_secondary'))
Text(this.isDark ? '深色模式' : '浅色模式')
.fontSize(16)
.fontColor($r('app.color.text_primary'))
}
.padding(16)
.backgroundColor($r('app.color.surface'))
.borderRadius(16)
.width('100%')
}
.width('100%')
.height('100%')
.padding(16)
.backgroundColor($r('app.color.background'))
}
@Builder
ThemeOption(title: string, mode: ThemeMode) {
Row() {
Text(title)
.fontSize(16)
.fontColor($r('app.color.text_primary'))
Blank()
Radio({ value: mode, group: 'theme' })
.checked(this.currentMode === mode)
.onChange((isChecked: boolean) => {
if (isChecked) {
this.currentMode = mode
this.themeManager.setThemeMode(mode)
}
})
}
.width('100%')
.height(48)
.padding({ left: 12, right: 12 })
}
}
import { preferences } from '@kit.ArkData'
import { ConfigurationConstant } from '@kit.AbilityKit'
// 主题模式枚举
export enum ThemeMode {
SYSTEM = 'system', // 跟随系统
LIGHT = 'light', // 浅色
DARK = 'dark' // 深色
}
// 主题管理类
export class ThemeManager {
private static instance: ThemeManager
private context: Context | null = null
private currentMode: ThemeMode = ThemeMode.SYSTEM
private systemIsDark: boolean = false
private listeners: ((isDark: boolean) => void)[] = []
static getInstance(): ThemeManager {
if (!ThemeManager.instance) {
ThemeManager.instance = new ThemeManager()
}
return ThemeManager.instance
}
// 初始化
async init(context: Context): Promise<void> {
this.context = context
await this.loadSavedMode()
}
// 加载保存的主题模式
private async loadSavedMode(): Promise<void> {
if (!this.context) return
try {
const prefs = await preferences.getPreferences(this.context, { name: 'settings' })
const mode = await prefs.get('themeMode', ThemeMode.SYSTEM) as ThemeMode
this.currentMode = mode
} catch (err) {
console.error('加载主题设置失败:', err)
}
}
// 设置主题模式
async setThemeMode(mode: ThemeMode): Promise<void> {
this.currentMode = mode
if (this.context) {
const prefs = await preferences.getPreferences(this.context, { name: 'settings' })
await prefs.put('themeMode', mode)
await prefs.flush()
}
this.notifyListeners()
}
// 更新系统主题状态
updateSystemColorMode(colorMode: ConfigurationConstant.ColorMode): void {
this.systemIsDark = colorMode === ConfigurationConstant.ColorMode.COLOR_MODE_DARK
if (this.currentMode === ThemeMode.SYSTEM) {
this.notifyListeners()
}
}
// 获取当前是否为深色模式
isDarkMode(): boolean {
switch (this.currentMode) {
case ThemeMode.LIGHT:
return false
case ThemeMode.DARK:
return true
case ThemeMode.SYSTEM:
default:
return this.systemIsDark
}
}
// 获取当前主题模式
getThemeMode(): ThemeMode {
return this.currentMode
}
// 添加监听器
addListener(listener: (isDark: boolean) => void): void {
this.listeners.push(listener)
}
// 移除监听器
removeListener(listener: (isDark: boolean) => void): void {
const index = this.listeners.indexOf(listener)
if (index > -1) {
this.listeners.splice(index, 1)
}
}
// 通知所有监听器
private notifyListeners(): void {
const isDark = this.isDarkMode()
this.listeners.forEach(listener => listener(isDark))
}
}
5. 在组件中使用主题颜色
@Component
struct ThemedCard {
build() {
Column({ space: 12 }) {
Text('标题')
.fontSize(18)
.fontWeight(FontWeight.Bold)
.fontColor($r('app.color.text_primary')) // 自动适配主题
Text('描述内容')
.fontSize(14)
.fontColor($r('app.color.text_secondary')) // 自动适配主题
Divider()
.color($r('app.color.divider')) // 自动适配主题
}
.padding(16)
.backgroundColor($r('app.color.surface')) // 自动适配主题
.borderRadius(16)
}
}
更多关于HarmonyOS 鸿蒙Next主题管理深色模式如何实现切换?暗黑模式适配指南的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
HarmonyOS Next主题管理通过ThemeManager模块实现深色模式切换。系统提供明暗主题资源目录(如resources/theme/dark),开发者需在config.json中配置主题资源。使用ThemeManager.applyTheme()方法动态切换主题,系统会自动加载对应资源。适配时需为所有UI组件定义明暗两套资源,确保颜色、图标等元素在不同模式下正确显示。系统主题变化会触发onConfigurationUpdate回调,可在此处理界面刷新逻辑。
在HarmonyOS Next中,实现深色/浅色主题切换主要依赖于其全新的主题管理框架。以下是核心实现方案:
1. 颜色资源配置
在resources/base/element/目录下的color.json文件中,必须使用语义化颜色命名,并分别定义浅色(light)和深色(dark)模式下的具体色值。
示例 (color.json):
{
"color": [
{
"name": "background_primary",
"value": "#FFFFFF",
"dark": "#000000"
},
{
"name": "text_primary",
"value": "#1A1A1A",
"dark": "#F0F0F0"
}
]
}
在UI组件中,通过$r('app.color.background_primary')引用这些语义化颜色资源,系统会根据当前主题自动匹配对应的色值。
2. 应用内主题切换
应用可以主动设置自身的主题,独立于系统主题。
核心API (themeManager):
import { themeManager } from '@kit.ArkUI';
// 获取当前应用主题
let currentTheme: themeManager.ThemeMode = themeManager.getTheme();
// 设置为深色主题
themeManager.setTheme(themeManager.ThemeMode.DARK);
// 设置为浅色主题
themeManager.setTheme(themeManager.ThemeMode.LIGHT);
// 跟随系统主题
themeManager.setTheme(themeManager.ThemeMode.AUTO);
当调用setTheme后,所有使用了语义化颜色的UI组件会自动刷新,无需手动更新每个组件。
3. 监听系统主题变化
应用可以注册监听器,实时响应系统主题的变更。
监听与取消监听:
import { themeManager } from '@kit.ArkUI';
// 定义监听回调函数
let systemThemeCallback = (theme: themeManager.ThemeMode): void => {
console.log(`System theme changed to: ${theme}`);
// 可以在此处执行一些额外的逻辑,但UI颜色会自动适配
};
// 注册监听(例如在aboutToAppear生命周期中)
themeManager.on('themeChange', systemThemeCallback);
// 取消监听(例如在aboutToDisappear生命周期中)
themeManager.off('themeChange', systemThemeCallback);
当系统主题改变且应用主题设置为ThemeMode.AUTO(跟随系统)时,此回调会被触发。
完整流程总结
- 配置资源:在
color.json中为所有关键颜色定义浅色和深色值。 - UI开发:在ArkUI组件中统一引用语义化颜色名称。
- 主题控制:使用
themeManager.setTheme()管理应用自身主题(深色、浅色或自动跟随系统)。 - 监听系统:通过
themeManager.on('themeChange', callback)监听系统主题变化,以便在需要时执行业务逻辑。
按照此方案,应用的主题切换将由系统框架自动完成渲染更新,开发者只需关注颜色资源的定义和主题模式的设置即可。

