本文同步发表于 微信公众号,微信搜索 程语新视界 即可关注,每个工作日都有文章更新

ArkTS开发框架支持应用内组件的主题换肤功能,包括:

  • 局部深浅色切换

  • 动态换肤

  • 自定义主题色

限制

  • 仅支持应用内组件级别设置,不支持UIAbility或窗口级别

  • 不支持C-API和Node-API

二、自定义主题色

2.1 创建自定义主题类

使用 CustomTheme 和 CustomColors 接口定义自定义主题色,仅需覆盖需要修改的Token字段,未覆盖的字段继承系统默认值。

示例:自定义主题色

import { CustomColors, CustomTheme } from '@kit.ArkUI';

export class AppColors implements CustomColors {
    // 自定义品牌色
    public brand: ResourceColor = '#FF75D9';
    // 使用系统资源,支持深浅色自动切换
    public warning: ResourceColor = $r('sys.color.ohos_id_color_warning');
}

export class AppTheme implements CustomTheme {
    public colors: AppColors = new AppColors();
}

export let gAppTheme: CustomTheme = new AppTheme();

三、设置应用内组件自定义主题色

3.1 在页面入口处设置

需在页面 build() 前调用 ThemeControl.setDefaultTheme()

示例:在Index.ets中设置

import { Theme, ThemeControl } from '@kit.ArkUI';
import { gAppTheme } from './AppTheme';

// 在页面build前设置默认主题
ThemeControl.setDefaultTheme(gAppTheme);

@Entry
@Component
struct DisplayPage {
    @State menuItemColor: ResourceColor = $r('sys.color.background_primary');

    // 组件生命周期回调,获取当前生效的主题
    onWillApplyTheme(theme: Theme) {
        this.menuItemColor = theme.colors.backgroundPrimary;
    }

    build() {
        Column() {
            List({ space: 10 }) {
                // 使用主题色设置背景
                ListItem() {
                    Column({ space: '5vp' }) {
                        Text('Color mode')
                    }
                    .backgroundColor(this.menuItemColor)
                }
                // ... 其他列表项
            }
        }
    }
}

3.2 在UIAbility中设置

在 onWindowStageCreate() 方法的 windowStage.loadContent 完成回调中设置主题。

示例:EntryAbility.ets

import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit';
import { window, CustomColors, ThemeControl } from '@kit.ArkUI';

class AppColors implements CustomColors {
    fontPrimary = 0xFFD53032;
    iconOnPrimary = 0xFFD53032;
    iconFourth = 0xFFD53032;
}

const abilityThemeColors = new AppColors();

export default class EntryAbility extends UIAbility {
    onWindowStageCreate(windowStage: window.WindowStage) {
        windowStage.loadContent('pages/Index', (err, data) => {
            if (err.code) {
                return;
            }
            // 在加载完成后设置主题
            ThemeControl.setDefaultTheme({ colors: abilityThemeColors });
        });
    }
}

注意事项

  • 若 setDefaultTheme 参数为 undefined,则清除自定义主题,恢复系统默认

  • 必须在ArkUI初始化后调用,即 windowStage.loadContent 的完成回调中

四、设置应用局部页面自定义主题

4.1 使用WithTheme容器

通过 WithTheme 容器为局部范围应用自定义主题,支持动态切换主题。

示例:动态切换主题

import { CustomColors, CustomTheme, Theme } from '@kit.ArkUI';

class AppColors implements CustomColors {
    public fontPrimary: ResourceColor = $r('app.color.brand_purple');
    public backgroundEmphasize: ResourceColor = $r('app.color.brand_purple');
}

class AppColorsSec implements CustomColors {
    public fontPrimary: ResourceColor = $r('app.color.brand');
    public backgroundEmphasize: ResourceColor = $r('app.color.brand');
}

class AppTheme implements CustomTheme {
    public colors: AppColors = new AppColors();
}

class AppThemeSec implements CustomTheme {
    public colors: AppColors = new AppColorsSec();
}

@Entry
@Component
struct DisplayPage1 {
    @State customTheme: CustomTheme = new AppTheme();
    @State message: ResourceStr = $r('app.string.SetCustomThemeStyle');
    count = 0;

    build() {
        WithTheme({ theme: this.customTheme }) {
            Column() {
                Text('WithTheme').fontSize(30)
                Text(this.message)
                Button('change theme').onClick(() => {
                    this.count++;
                    if (this.count > 1) this.count = 0;
                    switch (this.count) {
                        case 0: this.customTheme = new AppTheme(); break;
                        case 1: this.customTheme = new AppThemeSec(); break;
                    }
                })
            }
        }
    }
}

4.2 在BuilderNode中使用WithTheme

若在 BuilderNode 中使用 WithTheme,需手动传递系统环境变化事件以触发更新。

五、设置应用页面局部深浅色

5.1 使用WithTheme设置颜色模式

通过 WithTheme 的 colorMode 属性设置局部深浅色模式:

  • ThemeColorMode.SYSTEM:跟随系统

  • ThemeColorMode.LIGHT:固定浅色

  • ThemeColorMode.DARK:固定深色

示例:局部深浅色切换

import { ThemeControl, ThemeColorMode } from '@kit.ArkUI';

// 清除全局主题设置,确保局部设置生效
ThemeControl.setDefaultTheme(undefined);

@Entry
@Component
struct DisplayPage3 {
    @State message: string = 'Hello World';
    @State colorMode: ThemeColorMode = ThemeColorMode.DARK;

    build() {
        WithTheme({ colorMode: this.colorMode }) {
            Column() {
                Text(this.message)
                Button('Switch ColorMode').onClick(() => {
                    if (this.colorMode === ThemeColorMode.LIGHT) {
                        this.colorMode = ThemeColorMode.DARK;
                    } else if (this.colorMode === ThemeColorMode.DARK) {
                        this.colorMode = ThemeColorMode.LIGHT;
                    }
                })
            }
            .backgroundColor($r('sys.color.background_primary'))
        }
    }
}

5.2 深色模式资源准备

需在 resources/dark/element/ 目录下创建 dark.json 文件,定义深色资源。

示例:dark.json

{
    "color": [
        {
            "name": "start_window_background",
            "value": "#000000"
        }
    ]
}

六、系统缺省Token色值

系统提供一系列预定义Token,支持深浅色自动切换。以下是部分关键Token的默认值:

Token 场景类别 Light Dark
theme.colors.brand 品牌色 #ff0a59f7 #ff317af7
theme.colors.warning 一级警示色 #ffe84026 #ffd94838
theme.colors.fontPrimary 一级文本 #e5000000 #e5ffffff
theme.colors.fontSecondary 二级文本 #99000000 #99ffffff
theme.colors.backgroundPrimary 一级背景 #ffffffff #ffe5e5e5
theme.colors.backgroundSecondary 二级背景 #fff1f3f5 #ff191a1c
theme.colors.iconPrimary 一级图标 #e5000000 #e5ffffff
theme.colors.interactiveHover 悬停交互色 #0c000000 #0cffffff
theme.colors.interactivePressed 按压交互色 #19000000 #19ffffff

备注:完整Token列表参考官方文档中的表格。

总结

  1. 主题换肤支持:ArkTS支持应用内组件级别的主题换肤,包括自定义主题色和局部深浅色设置。

  2. 自定义主题:通过 CustomTheme 和 CustomColors 定义,使用 ThemeControl.setDefaultTheme() 全局应用。

  3. 局部主题:使用 WithTheme 容器实现局部主题或深浅色设置,支持动态切换。

  4. 系统Token:系统提供丰富的预定义Token,支持深浅色自动适配。

  5. 注意事项

    • 不支持UIAbility/窗口级主题设置

    • 在BuilderNode中使用需手动更新

    • 深色模式需准备对应的资源文件

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐