HarmonyOS 鸿蒙Next换肤功能怎么实现

发布于 1周前 作者 wuwangju 来自 鸿蒙OS

HarmonyOS 鸿蒙Next换肤功能怎么实现

APP换肤如何实现?。另外整体UI变灰色怎么实现?。

2 回复
目前有两种实现ArkTS 主题切换的方案,一种是基于ArkTS UI界面提供的深浅色模式接口,另一种是创建一个主题类来实现。 

深浅色模式目前有以下不足: 

1.只支持深浅色两种模式的切换,对于需要多个主题的场景不能满足。 

2.image组件(除了svg这种支持.fillColor()的)目前不支持深浅色模式的热加载,想要实现按钮图标的切换可能还是需要使用三元表达式,对于图标多的场景不够方便  

优点:系统规范较好 

主题类实现深浅色模式有以下不足: 

1.重新渲染ui的性能没有保障,还需要测试  

2.资源都继承在一个文件里,如果是很大的工程可能比较难管理 

3.相关代码规范问题  

优点: 可以支持多种主题的切换,只需要加切换函数就够了 支持按钮图标,图片热加载,支持多种资源根据主题切换,并实时重新渲染 在page中引用资源和传统方式的代码量差不多,能比较方便的使用,使用方法简单快捷 

参考demo: 

Index.ets

import theme from '../pages/theme'

@Entry

@Component

struct Index {

@State message: string = ‘normal mode’;

@StorageLink(‘current mode’) current_mode: string = ‘normal_mode’

@StorageLink(‘main_theme’) theme: theme = new theme(this.current_mode)

@StorageLink(‘gray mode’) gray_mode: number = 0;

build() {

Column() {

  Row() {

    Text(<span class="hljs-keyword">this</span>.message)

      .fontSize(<span class="hljs-number">50</span>)

      .fontColor(<span class="hljs-keyword">this</span>.theme.text_color)

      .fontWeight(FontWeight.Bold)

  }.justifyContent(FlexAlign.Center)

  .width(<span class="hljs-string">'100%'</span>)

  Row() {

    Column() {

      Image(<span class="hljs-keyword">this</span>.theme.phone_icon).objectFit(ImageFit.Contain)

      Text(<span class="hljs-string">'电话'</span>).fontColor(<span class="hljs-keyword">this</span>.theme.text_color)

      Image(<span class="hljs-keyword">this</span>.theme.camera_icon).objectFit(ImageFit.Contain)

      Text(<span class="hljs-string">'相机'</span>).fontColor(<span class="hljs-keyword">this</span>.theme.text_color)

    }.width(<span class="hljs-string">'22%'</span>).height(<span class="hljs-number">90</span>)

  }.width(<span class="hljs-string">'100%'</span>).alignItems(VerticalAlign.Top).height(<span class="hljs-string">'250vp'</span>).justifyContent(FlexAlign.SpaceEvenly)

  Row() {

    Button(<span class="hljs-string">'color mode'</span>)

      .width(<span class="hljs-string">'30%'</span>)

      .fontColor(<span class="hljs-keyword">this</span>.theme.text_color)

      .onClick(() =&gt; {

        <span class="hljs-keyword">this</span>.message = <span class="hljs-string">'color mode'</span>

        <span class="hljs-keyword">this</span>.theme.color_mode()

        <span class="hljs-keyword">this</span>.current_mode = <span class="hljs-string">'color_mode'</span>

      })

    Button(<span class="hljs-string">'normal mode'</span>)

      .width(<span class="hljs-string">'30%'</span>)

      .fontColor(<span class="hljs-keyword">this</span>.theme.text_color)

      .onClick(() =&gt; {

        <span class="hljs-keyword">this</span>.message = <span class="hljs-string">'normal mode'</span>

        <span class="hljs-keyword">this</span>.theme.normal_mode()

        <span class="hljs-keyword">this</span>.current_mode = <span class="hljs-string">'normal_mode'</span>

      })

    Button(<span class="hljs-string">'simple mode'</span>)

      .width(<span class="hljs-string">'30%'</span>)

      .fontColor(<span class="hljs-keyword">this</span>.theme.text_color)

      .onClick(() =&gt; {

        <span class="hljs-keyword">this</span>.message = <span class="hljs-string">'simple mode'</span>

        <span class="hljs-keyword">this</span>.theme.simple_mode()

        <span class="hljs-keyword">this</span>.current_mode = <span class="hljs-string">'simple_mode'</span>

      })

  }.height(<span class="hljs-number">50</span>)

  .justifyContent(FlexAlign.SpaceAround)

  .width(<span class="hljs-string">'100%'</span>)

  Image($r(<span class="hljs-string">'app.media.find_service'</span>)).objectFit(ImageFit.Contain).height(<span class="hljs-number">200</span>)

  <span class="hljs-comment">// 整体UI变灰色</span>

  Row() {

    Button(<span class="hljs-string">'gray mode off'</span>).fontColor(<span class="hljs-keyword">this</span>.theme.text_color).height(<span class="hljs-string">'30vp'</span>).onClick(() =&gt; <span class="hljs-keyword">this</span>.gray_mode = <span class="hljs-number">0</span>)

    Button(<span class="hljs-string">'gray mode on'</span>).fontColor(<span class="hljs-keyword">this</span>.theme.text_color).height(<span class="hljs-string">'30vp'</span>).onClick(() =&gt; <span class="hljs-keyword">this</span>.gray_mode = <span class="hljs-number">1</span>)

  }

}

.grayscale(<span class="hljs-keyword">this</span>.gray_mode)

.height(<span class="hljs-string">'100%'</span>).backgroundColor(<span class="hljs-keyword">this</span>.theme.background_color)

}

}<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 8px; right: 8px; font-size: 14px;">复制</button>

theme.ets

export default class theme {

//资源目录,将需要实现主题切换的资源变量存储在这

current_mode: string = ‘normal_mode’

earphone_icon: Resource = $r(‘app.media.ic_device_earphone_hero_filled’)

home_icon: Resource = $r(‘app.media.ic_public_home_filled’)

picture_icon: Resource = $r(‘app.media.ic_public_picture_filled’)

folder_icon: Resource = $r(‘app.media.ic_public_folder_filled’)

icon2: Resource = $r(‘app.media.ic_public_picture’)

color1: Resource = $r(‘app.color.red’)

font_color: Resource = $r(‘app.color.black’)

text_color: Resource = $r(‘app.color.black’)

background_color: Resource = $r(‘app.color.white’)

phone_icon: Resource = $r(‘app.media.dialer’)

market_icon: Resource = $r(‘app.media.shopping’)

notes_icon: Resource = $r(‘app.media.notes’)

setting_icon: Resource = $r(‘app.media.settings’)

camera_icon: Resource = $r(‘app.media.camera’)

photos_icon: Resource = $r(‘app.media.gallery’)

music_icon: Resource = $r(‘app.media.music’)

video_icon: Resource = $r(‘app.media.video’)

//通过读取current mode实现在重启应用后可以保存应用主题数据

constructor(current_mode: string) {

<span class="hljs-keyword">switch</span> (current_mode) {

  <span class="hljs-keyword">case</span> <span class="hljs-string">'normal_mode'</span>:

    <span class="hljs-keyword">this</span>.background_color = $r(<span class="hljs-string">'app.color.background'</span>)

    <span class="hljs-keyword">this</span>.text_color = $r(<span class="hljs-string">'app.color.brown'</span>)

    <span class="hljs-keyword">this</span>.phone_icon = $r(<span class="hljs-string">'app.media.dialer'</span>)

    <span class="hljs-keyword">this</span>.market_icon = $r(<span class="hljs-string">'app.media.shopping'</span>)

    <span class="hljs-keyword">this</span>.notes_icon = $r(<span class="hljs-string">'app.media.notes'</span>)

    <span class="hljs-keyword">this</span>.setting_icon = $r(<span class="hljs-string">'app.media.settings'</span>)

    <span class="hljs-keyword">this</span>.camera_icon = $r(<span class="hljs-string">'app.media.camera'</span>)

    <span class="hljs-keyword">this</span>.photos_icon = $r(<span class="hljs-string">'app.media.gallery'</span>)

    <span class="hljs-keyword">this</span>.music_icon = $r(<span class="hljs-string">'app.media.music'</span>)

    <span class="hljs-keyword">this</span>.video_icon = $r(<span class="hljs-string">'app.media.video'</span>)

    <span class="hljs-keyword">break</span>;

  <span class="hljs-keyword">case</span> <span class="hljs-string">'color_mode'</span>:

    <span class="hljs-keyword">this</span>.background_color = $r(<span class="hljs-string">'app.color.color_background'</span>)

    <span class="hljs-keyword">this</span>.text_color = $r(<span class="hljs-string">'app.color.yellow'</span>)

    <span class="hljs-keyword">this</span>.phone_icon = $r(<span class="hljs-string">'app.media.pwcall'</span>)

    <span class="hljs-keyword">this</span>.market_icon = $r(<span class="hljs-string">'app.media.pwshop'</span>)

    <span class="hljs-keyword">this</span>.notes_icon = $r(<span class="hljs-string">'app.media.pwnotes'</span>)

    <span class="hljs-keyword">this</span>.setting_icon = $r(<span class="hljs-string">'app.media.pwsetting'</span>)

    <span class="hljs-keyword">this</span>.camera_icon = $r(<span class="hljs-string">'app.media.pwcamera'</span>)

    <span class="hljs-keyword">this</span>.photos_icon = $r(<span class="hljs-string">'app.media.pwphotos'</span>)

    <span class="hljs-keyword">this</span>.music_icon = $r(<span class="hljs-string">'app.media.pwmusic'</span>)

    <span class="hljs-keyword">this</span>.video_icon = $r(<span class="hljs-string">'app.media.pwvideo'</span>)

    <span class="hljs-keyword">break</span>;

  <span class="hljs-keyword">case</span> <span class="hljs-string">'simple_mode'</span>:

    <span class="hljs-keyword">this</span>.background_color = $r(<span class="hljs-string">'app.color.white'</span>)

    <span class="hljs-keyword">this</span>.text_color = $r(<span class="hljs-string">'app.color.black'</span>)

    <span class="hljs-keyword">this</span>.phone_icon = $r(<span class="hljs-string">'app.media.simplicityCall'</span>)

    <span class="hljs-keyword">this</span>.market_icon = $r(<span class="hljs-string">'app.media.simplicityShop'</span>)

    <span class="hljs-keyword">this</span>.notes_icon = $r(<span class="hljs-string">'app.media.simplicityNotes'</span>)

    <span class="hljs-keyword">this</span>.setting_icon = $r(<span class="hljs-string">'app.media.simplicitySetting'</span>)

    <span class="hljs-keyword">this</span>.camera_icon = $r(<span class="hljs-string">'app.media.simplicityCamera'</span>)

    <span class="hljs-keyword">this</span>.photos_icon = $r(<span class="hljs-string">'app.media.simplicityPhotos'</span>)

    <span class="hljs-keyword">this</span>.music_icon = $r(<span class="hljs-string">'app.media.simplicityMusic'</span>)

    <span class="hljs-keyword">this</span>.video_icon = $r(<span class="hljs-string">'app.media.simplicityVideo'</span>)

    <span class="hljs-keyword">break</span>;

  <span class="hljs-keyword">default</span>:

    <span class="hljs-keyword">this</span>.current_mode = <span class="hljs-string">'normal_mode'</span>

    <span class="hljs-keyword">this</span>.background_color = $r(<span class="hljs-string">'app.color.background'</span>)

    <span class="hljs-keyword">this</span>.text_color = $r(<span class="hljs-string">'app.color.brown'</span>)

    <span class="hljs-keyword">this</span>.phone_icon = $r(<span class="hljs-string">'app.media.dialer'</span>)

    <span class="hljs-keyword">this</span>.market_icon = $r(<span class="hljs-string">'app.media.shopping'</span>)

    <span class="hljs-keyword">this</span>.notes_icon = $r(<span class="hljs-string">'app.media.notes'</span>)

    <span class="hljs-keyword">this</span>.setting_icon = $r(<span class="hljs-string">'app.media.settings'</span>)

    <span class="hljs-keyword">this</span>.camera_icon = $r(<span class="hljs-string">'app.media.camera'</span>)

    <span class="hljs-keyword">this</span>.photos_icon = $r(<span class="hljs-string">'app.media.gallery'</span>)

    <span class="hljs-keyword">this</span>.music_icon = $r(<span class="hljs-string">'app.media.music'</span>)

    <span class="hljs-keyword">this</span>.video_icon = $r(<span class="hljs-string">'app.media.video'</span>)

    <span class="hljs-keyword">break</span>;

}

}

//通过不同的主题切换函数更改主题变量,并在外部通过Appstorage实现应用内共享和画面重现渲染

light_mode() {

<span class="hljs-keyword">this</span>.font_color = $r(<span class="hljs-string">'app.color.black'</span>)

<span class="hljs-keyword">this</span>.background_color = $r(<span class="hljs-string">'app.color.white'</span>)

<span class="hljs-keyword">this</span>.earphone_icon = $r(<span class="hljs-string">'app.media.ic_device_earphone_hero_filled'</span>)

<span class="hljs-keyword">this</span>.home_icon = $r(<span class="hljs-string">'app.media.ic_public_home_filled'</span>)

<span class="hljs-keyword">this</span>.picture_icon = $r(<span class="hljs-string">'app.media.ic_public_picture_filled'</span>)

<span class="hljs-keyword">this</span>.folder_icon = $r(<span class="hljs-string">'app.media.ic_public_folder_filled'</span>)

}

dark_mode() {

<span class="hljs-keyword">this</span>.font_color = $r(<span class="hljs-string">'app.color.white'</span>)

<span class="hljs-keyword">this</span>.background_color = $r(<span class="hljs-string">'app.color.background'</span>)

<span class="hljs-keyword">this</span>.earphone_icon = $r(<span class="hljs-string">'app.media.ic_device_earphone_hero'</span>)

<span class="hljs-keyword">this</span>.home_icon = $r(<span class="hljs-string">'app.media.ic_public_home'</span>)

<span class="hljs-keyword">this</span>.picture_icon = $r(<span class="hljs-string">'app.media.ic_public_picture'</span>)

<span class="hljs-keyword">this</span>.folder_icon = $r(<span class="hljs-string">'app.media.ic_public_folder'</span>)

}

normal_mode() {

<span class="hljs-keyword">this</span>.current_mode = <span class="hljs-string">'normal_mode'</span>

<span class="hljs-keyword">this</span>.background_color = $r(<span class="hljs-string">'app.color.background'</span>)

<span class="hljs-keyword">this</span>.text_color = $r(<span class="hljs-string">'app.color.brown'</span>)

<span class="hljs-keyword">this</span>.phone_icon = $r(<span class="hljs-string">'app.media.dialer'</span>)

<span class="hljs-keyword">this</span>.market_icon = $r(<span class="hljs-string">'app.media.shopping'</span>)

<span class="hljs-keyword">this</span>.notes_icon = $r(<span class="hljs-string">'app.media.notes'</span>)

<span class="hljs-keyword">this</span>.setting_icon = $r(<span class="hljs-string">'app.media.settings'</span>)

<span class="hljs-keyword">this</span>.camera_icon = $r(<span class="hljs-string">'app.media.camera'</span>)

<span class="hljs-keyword">this</span>.photos_icon = $r(<span class="hljs-string">'app.media.gallery'</span>)

<span class="hljs-keyword">this</span>.music_icon = $r(<span class="hljs-string">'app.media.music'</span>)

<span class="hljs-keyword">this</span>.video_icon = $r(<span class="hljs-string">'app.media.video'</span>)

}

color_mode() {

<span class="hljs-keyword">this</span>.current_mode = <span class="hljs-string">'color_mode'</span>

<span class="hljs-keyword">this</span>.background_color = $r(<span class="hljs-string">'app.color.color_background'</span>)

<span class="hljs-keyword">this</span>.text_color = $r(<span class="hljs-string">'app.color.yellow'</span>)

<span class="hljs-keyword">this</span>.phone_icon = $r(<span class="hljs-string">'app.media.pwcall'</span>)

<span class="hljs-keyword">this</span>.market_icon = $r(<span class="hljs-string">'app.media.pwshop'</span>)

<span class="hljs-keyword">this</span>.notes_icon = $r(<span class="hljs-string">'app.media.pwnotes'</span>)

<span class="hljs-keyword">this</span>.setting_icon = $r(<span class="hljs-string">'app.media.pwsetting'</span>)

<span class="hljs-keyword">this</span>.camera_icon = $r(<span class="hljs-string">'app.media.pwcamera'</span>)

<span class="hljs-keyword">this</span>.photos_icon = $r(<span class="hljs-string">'app.media.pwphotos'</span>)

<span class="hljs-keyword">this</span>.music_icon = $r(<span class="hljs-string">'app.media.pwmusic'</span>)

<span class="hljs-keyword">this</span>.video_icon = $r(<span class="hljs-string">'app.media.pwvideo'</span>)

}

simple_mode() {

<span class="hljs-keyword">this</span>.current_mode = <span class="hljs-string">'simple_mode'</span>

<span class="hljs-keyword">this</span>.background_color = $r(<span class="hljs-string">'app.color.white'</span>)

<span class="hljs-keyword">this</span>.text_color = $r(<span class="hljs-string">'app.color.black'</span>)

<span class="hljs-keyword">this</span>.phone_icon = $r(<span class="hljs-string">'app.media.simplicityCall'</span>)

<span class="hljs-keyword">this</span>.market_icon = $r(<span class="hljs-string">'app.media.simplicityShop'</span>)

<span class="hljs-keyword">this</span>.notes_icon = $r(<span class="hljs-string">'app.media.simplicityNotes'</span>)

<span class="hljs-keyword">this</span>.setting_icon = $r(<span class="hljs-string">'app.media.simplicitySetting'</span>)

<span class="hljs-keyword">this</span>.camera_icon = $r(<span class="hljs-string">'app.media.simplicityCamera'</span>)

<span class="hljs-keyword">this</span>.photos_icon = $r(<span class="hljs-string">'app.media.simplicityPhotos'</span>)

<span class="hljs-keyword">this</span>.music_icon = $r(<span class="hljs-string">'app.media.simplicityMusic'</span>)

<span class="hljs-keyword">this</span>.video_icon = $r(<span class="hljs-string">'app.media.simplicityVideo'</span>)

}

}<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 8px; right: 8px; font-size: 14px;">复制</button>

在resource目录下创建了dark/element目录、dark/media目录。element创建 color.json资源 ,在 media中 存放图片资源。适配手机深色模式。

更多关于HarmonyOS 鸿蒙Next换肤功能怎么实现的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


HarmonyOS 鸿蒙Next换肤功能实现主要依赖于系统级的主题管理能力和应用层面的皮肤资源适配。

  1. 系统主题管理:HarmonyOS 提供了主题管理接口,允许开发者定义和应用不同的主题。这些主题可以包含颜色、字体、图标等元素的配置。开发者可以通过系统API获取当前主题设置,并据此调整应用的UI表现。

  2. 皮肤资源准备:为实现换肤,开发者需要准备多套皮肤资源,如不同主题的布局文件、颜色资源、图片资源等。这些资源应按照一定规则组织,便于动态加载和切换。

  3. 动态加载与切换:在运行时,应用可以监听系统主题变化事件,或通过用户操作触发换肤。一旦收到换肤指令,应用应动态加载相应的皮肤资源,并更新UI组件以反映新主题。

  4. 资源优化:为确保换肤过程的流畅性,开发者应对皮肤资源进行优化,如使用Drawable对象复用、减少资源文件大小等。

  5. 兼容性测试:在不同设备、不同系统版本上测试换肤功能,确保兼容性和稳定性。

如果问题依旧没法解决请联系官网客服,官网地址是:https://www.itying.com/category-93-b0.html。

回到顶部