1# 设置应用内主题换肤 2 3## 概述 4 5对于采用ArkTS开发的应用,提供了应用内组件的主题换肤功能,支持局部的深浅色切换及动态换肤。目前,该功能只支持设置应用内主题换肤,暂不支持在UIAbility或窗口层面进行主题设置,同时也不支持C-API和Node-API。 6 7## 自定义主题色 8当应用需要使用换肤功能时,应自定义主题颜色。[CustomTheme](../reference/apis-arkui/js-apis-arkui-theme.md#customtheme)用于自定义主题色的内容,其属性可选,仅需要复写需修改的部分,未修改内容将继承系统默认设置,可参考[系统默认的token颜色值](#系统缺省token色值)。请参照以下示例自定义主题色: 9 10 ```ts 11 import { CustomColors, CustomTheme } from '@kit.ArkUI' 12 13 export class AppColors implements CustomColors { 14 //自定义主题色 15 brand: ResourceColor = '#FF75D9'; 16 } 17 18 export class AppTheme implements CustomTheme { 19 public colors: AppColors = new AppColors() 20 } 21 22 export let gAppTheme: CustomTheme = new AppTheme() 23 ``` 24 25## 设置应用内组件自定义主题色 26- 可以在页面入口处统一设置应用内组件自定义主题色,但需确保在页面build前执行[ThemeControl](../reference/apis-arkui/js-apis-arkui-theme.md#themecontrol)。 27 其中,[onWillApplyTheme](../reference/apis-arkui/arkui-ts/ts-custom-component-lifecycle.md#onwillapplytheme12)回调函数用于使自定义组件获取当前生效的Theme对象。 28 29 ```ts 30 import { Theme, ThemeControl } from '@kit.ArkUI' 31 import { gAppTheme } from './AppTheme' 32 33 //在页面build前执行ThemeControl 34 ThemeControl.setDefaultTheme(gAppTheme) 35 36 @Entry 37 @Component 38 struct DisplayPage { 39 @State menuItemColor: ResourceColor = $r('sys.color.background_primary') 40 41 onWillApplyTheme(theme: Theme) { 42 this.menuItemColor = theme.colors.backgroundPrimary; 43 } 44 45 build() { 46 Column() { 47 List({ space: 10 }) { 48 ListItem() { 49 Column({ space: '5vp' }) { 50 Text('Color mode') 51 .margin({ top: '5vp', left: '14fp' }) 52 .width('100%') 53 Row() { 54 Column() { 55 Text('Light') 56 .fontSize('16fp') 57 .textAlign(TextAlign.Start) 58 .alignSelf(ItemAlign.Center) 59 Radio({ group: 'light or dark', value: 'light' }) 60 .checked(true) 61 } 62 .width('50%') 63 64 Column() { 65 Text('Dark') 66 .fontSize('16fp') 67 .textAlign(TextAlign.Start) 68 .alignSelf(ItemAlign.Center) 69 Radio({ group: 'light or dark', value: 'dark' }) 70 } 71 .width('50%') 72 } 73 } 74 .width('100%') 75 .height('90vp') 76 .borderRadius('10vp') 77 .backgroundColor(this.menuItemColor) 78 } 79 80 ListItem() { 81 Column() { 82 Text('Brightness') 83 .width('100%') 84 .margin({ top: '5vp', left: '14fp' }) 85 Slider({ value: 40, max: 100 }) 86 } 87 .width('100%') 88 .height('70vp') 89 .borderRadius('10vp') 90 .backgroundColor(this.menuItemColor) 91 } 92 93 ListItem() { 94 Column() { 95 Row() { 96 Column({ space: '5vp' }) { 97 Text('Touch sensitivity') 98 .fontSize('16fp') 99 .textAlign(TextAlign.Start) 100 .width('100%') 101 Text('Increase the touch sensitivity of your screen' + 102 ' for use with screen protectors') 103 .fontSize('12fp') 104 .fontColor(Color.Blue) 105 .textAlign(TextAlign.Start) 106 .width('100%') 107 } 108 .alignSelf(ItemAlign.Center) 109 .margin({ left: '14fp' }) 110 .width('75%') 111 112 Toggle({ type: ToggleType.Switch, isOn: true }) 113 .margin({ right: '14fp' }) 114 .alignSelf(ItemAlign.Center) 115 } 116 .width('100%') 117 .height('80vp') 118 } 119 .width('100%') 120 .borderRadius('10vp') 121 .backgroundColor(this.menuItemColor) 122 } 123 } 124 } 125 .padding('10vp') 126 .backgroundColor('#dcdcdc') 127 .width('100%') 128 .height('100%') 129 } 130 } 131 ``` 132 133- 在UIAbility中设置[ThemeControl](../reference/apis-arkui/js-apis-arkui-theme.md#themecontrol),需要在onWindowStageCreate()方法中[setDefaultTheme](../reference/apis-arkui/js-apis-arkui-theme.md#setdefaulttheme),设置应用内组件的自定义主题色。 134 135 ```ts 136 import {AbilityConstant, UIAbility, Want } from '@kit.AbilityKit'; 137 import { hilog } from '@kit.PerformanceAnalysisKit'; 138 import { window, CustomColors, ThemeControl } from '@kit.ArkUI'; 139 140 class AppColors implements CustomColors { 141 fontPrimary = 0xFFD53032 142 iconOnPrimary = 0xFFD53032 143 iconFourth = 0xFFD53032 144 } 145 146 const abilityThemeColors = new AppColors(); 147 148 export default class EntryAbility extends UIAbility { 149 onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) { 150 hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate'); 151 } 152 153 onDestroy() { 154 hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy'); 155 } 156 157 onWindowStageCreate(windowStage: window.WindowStage) { 158 // Main window is created, set main page for this ability 159 hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate'); 160 161 windowStage.loadContent('pages/Index', (err, data) => { 162 if (err.code) { 163 hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? ''); 164 return; 165 } 166 hilog.info(0x0000, 'testTag', 'Succeeded in loading the content. Data: %{public}s', JSON.stringify(data) ?? ''); 167 // 在onWindowStageCreate()方法中setDefaultTheme 168 ThemeControl.setDefaultTheme({ colors: abilityThemeColors }) 169 hilog.info(0x0000, 'testTag', '%{public}s', 'ThemeControl.setDefaultTheme done'); 170 }); 171 } 172 173 } 174 ``` 175 176 177 178> **说明:** 179> 180>如果setDefaultTheme的参数为undefined时,默认token值对应的色值参考[系统缺省token色值](#系统缺省token色值)。 181 182## 设置应用局部页面自定义主题风格 183通过设置[WithTheme](../reference/apis-arkui/arkui-ts/ts-container-with-theme.md#withetheme),将自定义主题Theme的配色应用于内部组件的默认样式。在WithTheme的作用范围内,组件的配色会根据Theme的配色进行调整。 184 185如示例所示,使用WithTheme({ theme: this.myTheme })可将作用域内组件的配色设置为自定义主题风格。后续可以通过更新this.myTheme来更换主题风格。[onWillApplyTheme](../reference/apis-arkui/arkui-ts/ts-custom-component-lifecycle.md#onwillapplytheme12)回调函数用于使自定义组件能够获取当前生效的Theme对象。 186 187 ```ts 188 import { CustomColors, CustomTheme, Theme } from '@kit.ArkUI' 189 190 class AppColors implements CustomColors { 191 fontPrimary: ResourceColor = $r('app.color.brand_purple') 192 backgroundEmphasize: ResourceColor = $r('app.color.brand_purple') 193 } 194 195 class AppColorsSec implements CustomColors { 196 fontPrimary: ResourceColor = $r('app.color.brand') 197 backgroundEmphasize: ResourceColor = $r('app.color.brand') 198 } 199 200 class AppTheme implements CustomTheme { 201 public colors: AppColors = new AppColors() 202 } 203 204 class AppThemeSec implements CustomTheme { 205 public colors: AppColors = new AppColorsSec() 206 } 207 208 @Entry 209 @Component 210 struct DisplayPage { 211 @State customTheme: CustomTheme = new AppTheme() 212 @State message: string = '设置应用局部页面自定义主题风格' 213 count = 0; 214 215 build() { 216 WithTheme({ theme: this.customTheme }) { 217 Row(){ 218 Column() { 219 Text('WithTheme') 220 .fontSize(30) 221 .margin({bottom: 10}) 222 Text(this.message) 223 .margin({bottom: 10}) 224 Button('change theme').onClick(() => { 225 this.count++; 226 if (this.count > 1) { 227 this.count = 0; 228 } 229 switch (this.count) { 230 case 0: 231 this.customTheme = new AppTheme(); 232 break; 233 case 1: 234 this.customTheme = new AppThemeSec(); 235 break; 236 } 237 }) 238 } 239 .width('100%') 240 } 241 .height('100%') 242 .width('100%') 243 } 244 } 245 } 246 ``` 247 248 249 250## 设置应用页面局部深浅色 251通过[WithTheme](../reference/apis-arkui/arkui-ts/ts-container-with-theme.md#withetheme)可以设置三种颜色模式,跟随系统模式,浅色模式和深色模式。 252 253在WithTheme的作用范围内,组件的样式资源值会根据指定的模式,读取对应的深浅色模式系统和应用资源值。这意味着,在WithTheme作用范围内,组件的配色会根据所指定的深浅模式进行调整。 254 255如下面的示例所示,通过WithTheme({ colorMode: ThemeColorMode.DARK }),可以将作用范围内的组件设置为深色模式。 256 257设置局部深浅色时,需要添加dark.json资源文件,深浅色模式才会生效。 258 259 260 261dark.json数据示例: 262 ```ts 263 { 264 "color": [ 265 { 266 "name": "start_window_background", 267 "value": "#FFFFFF" 268 } 269 ] 270 } 271 ``` 272 273 ```ts 274 @Entry 275 @Component 276 struct DisplayPage { 277 @State message: string = 'Hello World'; 278 @State colorMode: ThemeColorMode = ThemeColorMode.DARK; 279 280 build() { 281 WithTheme({ colorMode: this.colorMode }) { 282 Row() { 283 Column() { 284 Text(this.message) 285 .fontSize(50) 286 .fontWeight(FontWeight.Bold) 287 Button('Switch ColorMode').onClick(() => { 288 if (this.colorMode === ThemeColorMode.LIGHT) { 289 this.colorMode = ThemeColorMode.DARK; 290 } else if (this.colorMode === ThemeColorMode.DARK) { 291 this.colorMode = ThemeColorMode.LIGHT; 292 } 293 }) 294 } 295 .width('100%') 296 } 297 .backgroundColor($r('sys.color.background_primary')) 298 .height('100%') 299 .expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP, SafeAreaEdge.END, SafeAreaEdge.BOTTOM, SafeAreaEdge.START]) 300 } 301 } 302 } 303 ``` 304 305 306 307## 系统缺省token色值 308 309| Token | 场景类别 | Light | | Dark | | 310|--------------------------------------------|-----| --- |-----------| ------- | -------------------------------------------- | 311| theme.colors.brand | 品牌色 |#ff0a59f7|  |#ff317af7|| 312| theme.colors.warning | 一级警示色 |#ffe84026|  |#ffd94838|| 313| theme.colors.alert | 二级警示色 |#ffed6f21|  |#ffdb6b42|| 314| theme.colors.confirm | 确认色 |#ff64bb5c|  |#ff5ba854|| 315| theme.colors.fontPrimary | 一级文本 | #e5000000 |  |#e5ffffff|| 316| theme.colors.fontSecondary | 二级文本 | #99000000 |  |#99ffffff|| 317| theme.colors.fontTertiary | 三级文本 | #66000000 |  |#66ffffff|| 318| theme.colors.fontFourth | 四级文本 | #33000000 |  |#33ffffff|| 319| theme.colors.fontEmphasize | 高亮文本 | #ff0a59f7 |  |#ff317af7|| 320| theme.colors.fontOnPrimary | 一级文本反色 | #ffffffff |  |#ff000000|| 321| theme.colors.fontOnSecondary | 二级文本反色 | #99ffffff |  |#99000000|| 322| theme.colors.fontOnTertiary | 三级文本反色 | #66ffffff |  |#66000000|| 323| theme.colors.fontOnFourth | 四级文本反色 | #33ffffff |  |#33000000|| 324| theme.colors.iconPrimary | 一级图标 | #e5000000 |  |#e5ffffff|| 325| theme.colors.iconSecondary | 二级图标 | #99000000 |  |#99ffffff|| 326| theme.colors.iconTertiary | 三级图标 | #66000000 |  |#66ffffff|| 327| theme.colors.iconFourth | 四级图标 | #33000000 |  |#33ffffff|| 328| theme.colors.iconEmphasize | 高亮图标 | #ff0a59f7 |  |#ff317af7|| 329| theme.colors.iconSubEmphasize | 高亮辅助图标 | #660a59f7 |  |#66317af7|| 330| theme.colors.iconOnPrimary | 一级图标反色 | #ffffffff |  |#ff000000|| 331| theme.colors.iconOnSecondary | 二级图标反色 | #99ffffff |  |#99000000|| 332| theme.colors.iconOnTertiary | 三级图标反色 | #66ffffff |  |#66000000|| 333| theme.colors.iconOnFourth | 四级图标反色 | #33ffffff |  |#33000000|| 334| theme.colors.backgroundPrimary | 一级背景(实色/不透明色) | #ffffffff |  |#ffe5e5e5|| 335| theme.colors.backgroundSecondary | 二级背景(实色/不透明色) | #fff1f3f5 |  |#ff191a1c|| 336| theme.colors.backgroundTertiary | 三级背景(实色/不透明色) | #ffe5e5ea |  |#ff202224|| 337| theme.colors.backgroundFourth | 四级背景(实色/不透明色) | #ffd1d1d6 |  |#ff2e3033|| 338| theme.colors.backgroundEmphasize | 高亮背景(实色/不透明色) | #ff0a59f7 |  |#ff317af7|| 339| theme.colors.compForegroundPrimary | 前背景 | #ff000000 |  | #ffe5e5e5 || 340| theme.colors.compBackgroundPrimary | 白色背景 | #ffffffff || #ffffffff || 341| theme.colors.compBackgroundPrimaryTran | 白色透明背景 | #ffffffff || #33ffffff || 342| theme.colors.compBackgroundPrimaryContrary | 常亮背景 | #ffffffff || #ffe5e5e5 || 343| theme.colors.compBackgroundGray | 灰色背景 | #fff1f3f5 || #ffe5e5ea || 344| theme.colors.compBackgroundSecondary | 二级背景 | #19000000 || #19ffffff || 345| theme.colors.compBackgroundTertiary | 三级背景 | #0c000000 || #0cffffff || 346| theme.colors.compBackgroundEmphasize | 高亮背景 | #ff0a59f7 || #ff317af7 || 347| theme.colors.compBackgroundNeutral | 黑色中性高亮背景 | #ff000000 || #ffffffff || 348| theme.colors.compEmphasizeSecondary | 20%高亮背景 | #330a59f7 || #33317af7 || 349| theme.colors.compEmphasizeTertiary | 10%高亮背景 | #190a59f7 || #19317af7 || 350| theme.colors.compDivider | 分割线颜色 | #33000000 || #33ffffff || 351| theme.colors.compCommonContrary | 通用反色 | #ffffffff || #ff000000 || 352| theme.colors.compBackgroundFocus | 获焦态背景色 | #fff1f3f5 || #ff000000 || 353| theme.colors.compFocusedPrimary | 获焦态一级反色 | #e5000000 || #e5ffffff || 354| theme.colors.compFocusedSecondary | 获焦态二级反色 | #99000000 || #99ffffff || 355| theme.colors.compFocusedTertiary | 获焦态三级反色 | #66000000 || #66ffffff || 356| theme.colors.interactiveHover | 通用悬停交互式颜色 | #0c000000 || #0cffffff || 357| theme.colors.interactivePressed | 通用按压交互式颜色 | #19000000 || #19ffffff || 358| theme.colors.interactiveFocus | 通用获焦交互式颜色 | #ff0a59f7 || #ff317af7 || 359| theme.colors.interactiveActive | 通用激活交互式颜色 | #ff0a59f7 || #ff317af7 || 360| theme.colors.interactiveSelect | 通用选择交互式颜色 | #33000000 || #33ffffff || 361| theme.colors.interactiveClick | 通用点击交互式颜色 | #19000000 || #19ffffff || 362