HarmonyOS鸿蒙Next中多主题颜色资源文件如何切换引用

HarmonyOS鸿蒙Next中多主题颜色资源文件如何切换引用 客户需要做多种颜色主题,并且每种主题都有一个color.json文件,如何在切换主题时切换引入不同的color.json 大概有8个这样的文件。

7 回复

resources目录下为每个主题创建独立子目录(如theme1theme2),每个目录中放置对应的color.json

resources/
├── theme1/
│   └── element/
│       └── `color`.json  
├── theme2/
│   └── element/
│       └── `color`.json

所有主题的color.json中需保持相同颜色ID定义,仅改变色值:

// theme1/`color`.json
{
  "color": [
    { "name": "primary_color", "value": "#FF0000" }
  ]
}

// theme2/`color`.json
{
  "color": [
    { "name": "primary_color", "value": "#00FF00" }
  ]
}

创建全局状态管理类存储当前主题标识:

class ThemeManager {
  private currentTheme: string = 'theme1';

  setTheme(themeName: string) {
    this.currentTheme = themeName;
    // 触发界面重绘逻辑
  }
}

通过字符串拼接方式动态加载对应主题资源:

function getDynamicColor(resName: string) {
  const themePath = `app.${ThemeManager.currentTheme}.color.${resName}`;
  return $r(themePath);
}

// 使用示例
Text('主题文字')
  .fontColor(getDynamicColor('primary_color'))

更多关于HarmonyOS鸿蒙Next中多主题颜色资源文件如何切换引用的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


这种方式依赖于切换流程中重新执行属性设置代码,随着系统的发展和性能优化,并不能确保所有属性代码均被重新执行。因为在大部分热更新场景中,重新执行全部页面构建和属性设置代码显然是冗余的。

我都觉得这都是最优解了,但是不知道为什么官方不推荐 https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/ui-dark-light-color-adaptation#

一楼的方法可以借鉴参考的,我们内部实现主体切换也是这种思路,也可以参考官方的主体切换,参考文档:ThemeControlWithTheme-主题-ArkTS组件-ArkUI(方舟UI框架)-应用框架 - 华为HarmonyOS开发者

class AppColors implements CustomColors { fontPrimary: ResourceColor = $r(‘sys.color.font_primary’) brand: ResourceColor = $r(‘sys.color.brand’)

/**

  • other Colors */ }

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

@Entry @Component struct DisplayPage { arr = [‘color1.json’,//‘color8.json’] @State customTheme: CustomTheme = new AppTheme();

build() { WithTheme({ theme: this.customTheme }) {

  Column() {
    Text('WithTheme')
      .fontSize(30)
      .margin({ bottom: 10 })
    ForEach(this.arr,(item:string)){
      Button(item).onClick(() => {
        this.changeColor(item)
      })
    }
  }
  .height('100%')
  .width('100%')
  .backgroundColor(this.customTheme.colors!.backgroundPrimary)
}

}

async changeColor(colorJsonFileName: string) { const data: Uint8Array | void = await this.getUIContext().getHostContext()?.resourceManager.getRawFileContent(colorJsonFileName) if (data) { const jsonStr = util.TextDecoder.create(“utf-8”, { ignoreBOM: true }).decodeToString(new Uint8Array(data.buffer)); const jsonObj = JSON.parse(jsonStr) const theme = new AppTheme() theme.colors.fontPrimary = Object(jsonObj)[‘font_primary’] theme.colors.brand = Object(jsonObj)[‘brand’] /** * other Colors */ this.customTheme = theme } } }

这8个color.json可以放raw里面,点击切换读取对应的color.json解析json然后把颜色值赋值给CustomColors。

系统多主题的设置方式参考以下文档:

https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/theme_skinning#%E8%87%AA%E5%AE%9A%E4%B9%89%E4%B8%BB%E9%A2%98%E8%89%B2

通过class类实现定义不同的颜色, 同时根据appstorage决定加载哪个色系的class, 应该是可以实现的. 但这个例子颜色都是直接定义在ets文件中, 不知道能不能从color.js中读取.

在HarmonyOS Next中,可通过theme模块实现多主题颜色资源切换。步骤如下:

  1. resources/base/theme目录下定义不同主题的json文件(如dark.json/light.json),包含颜色资源ID和对应值。

  2. 在代码中使用this.context.resourceManager.getTheme获取主题管理器,调用setTheme(id)切换主题(id对应主题json文件名)。

  3. 在布局中直接引用主题颜色资源ID(如$color:primary_color),系统会自动根据当前主题切换实际颜色值。

注意:主题切换后需手动刷新UI,调用this.context.resourceManager.updateConfiguration触发资源更新。

在HarmonyOS Next中实现多主题颜色资源切换,可以通过以下方式实现:

  1. 资源文件组织:
  • 在resources目录下按主题分类存放color.json文件
  • 例如:resources/theme1/color.json、resources/theme2/color.json等
  1. 动态切换实现:
// 获取当前资源管理器
let resourceManager = getContext().resourceManager;

// 设置主题路径
async function setTheme(themeName: string) {
  try {
    // 先清除当前主题
    resourceManager.release();
    // 加载新主题资源
    await resourceManager.load("/resources/" + themeName);
  } catch (err) {
    console.error(`切换主题失败: ${err}`);
  }
}

// 使用示例
setTheme("theme1");
  1. 资源引用: 切换后可以直接通过资源ID引用,系统会自动使用当前主题下的颜色值
$r('app.color.primary_color')
  1. 注意事项:
  • 确保各主题下的color.json中定义的资源ID保持一致
  • 主题切换可能需要重新渲染UI组件以生效
  • 考虑将当前主题设置持久化存储

这种方法可以实现运行时动态切换主题,无需重新启动应用。

回到顶部