HarmonyOS 如何实现应用全局换肤功能

HarmonyOS
2天前
浏览
收藏 0
回答 1
待解决
回答 1
按赞同
/
按时间
Heiang

涉及到的图片资源需自行替换,参考示例如下:

index.ets

import ConfigurationConstant from '@ohos.app.ability.ConfigurationConstant';
import theme from '../pages/theme'
import router from '@ohos.router';
import { common } from '@kit.AbilityKit';
import { TestImgToFile } from "./TestImgToFile"


PersistentStorage.persistProp('gray mode', 0)
PersistentStorage.persistProp('current mode', 'normal_mode')

@Entry
@Component
struct Index {
  @StorageProp('currentColorMode') @Watch('onColorModeChange') currentMode: number =
    ConfigurationConstant.ColorMode.COLOR_MODE_LIGHT;
  @State private defaultUserIcon: Resource = $r("app.media.person");
  @State message: string = 'light mode';
  @State homepic: Resource = $r('app.media.ic_public_home')
  @StorageLink('gray mode') gray_mode: number = 0;
  @StorageLink('current mode') current_mode: string = 'normal_mode'
  @StorageLink('main_theme') theme: theme = new theme(this.current_mode)

  aboutToAppear() {
    this.setDefaultUserIconByColorModel();
  }

  // 深色模式变化,登录账号的默认头像也随之变化
  onColorModeChange() {
    this.setDefaultUserIconByColorModel();
  }

  // 根据深浅色切换加载用户默认头像
  setDefaultUserIconByColorModel() {
    this.defaultUserIcon = this.currentMode == ConfigurationConstant.ColorMode.COLOR_MODE_LIGHT ?
    $r("app.media.startIcon") : $r("app.media.ic_public_home");
  }

  build() {

    Row() {
      Column() {
        TestImgToFile().width("100%").height("50vp")
        Button("切换下载图片").onClick(() => {
          //切换前请先保存图片获取地址
          this.theme.setDownPic(["pixel.jpg"])
          theme.isDown = true
          console.log(this.theme.setting_icon.toString())
        })
        Column() {
          Text(this.message)
            .fontSize(50)
            .fontWeight(FontWeight.Bold)
            .fontColor($r('app.color.font_color'))
          Row() {
            Image($r("app.media.ic_public_favor"))
              .width(100)
              .height(100)
              .padding(12)
              .fillColor($r('sys.color.ohos_id_color_primary'))
          }

          Text('dark mode')
            .height('100vp')
            .fontColor($r('app.color.font_color'))//('sys.color.ohos_id_color_primary')
            .onClick(() => {
              this.message = 'dark mode'
              let context = getContext() as common.UIAbilityContext
              context.getApplicationContext().setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_DARK);

            })
          Text('light mode')
            .height('100vp')
            .fontColor($r('app.color.font_color'))
            .onClick(() => {
              this.message = 'light mode'
              let context = getContext() as common.UIAbilityContext
              context.getApplicationContext().setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_LIGHT);

            })
        }.backgroundColor($r('app.color.background'))

        Row() {
          Column() {
            Image(this.theme.phone_icon).objectFit(ImageFit.Contain)
            Text('电话').fontColor(this.theme.text_color)
            Image(this.theme.camera_icon).objectFit(ImageFit.Contain)
            Text('相机').fontColor(this.theme.text_color)
          }.width('22%').height(90)

          Column() {
            Image(this.theme.market_icon).objectFit(ImageFit.Contain)
            Text('商城').fontColor(this.theme.text_color)
            Image(this.theme.photos_icon).objectFit(ImageFit.Contain)
            Text('相册').fontColor(this.theme.text_color)
          }.width('22%').height(90)

          Column() {
            Image(this.theme.notes_icon).objectFit(ImageFit.Contain)
            Text('备忘录').fontColor(this.theme.text_color)
            Image(this.theme.music_icon).objectFit(ImageFit.Contain)
            Text('音乐').fontColor(this.theme.text_color)
          }.width('22%').height(90)

          Column() {
            Image(this.theme.setting_icon).objectFit(ImageFit.Contain)
            Text('设置').fontColor(this.theme.text_color)
            Image(this.theme.video_icon).objectFit(ImageFit.Contain)
            Text('视频').fontColor(this.theme.text_color)
          }.width('22%').height(90)
        }.width('100%').alignItems(VerticalAlign.Top).height('250vp').justifyContent(FlexAlign.SpaceEvenly)

        Image($r('app.media.setting'))
          .height('100vp')
          .fillColor($r('sys.color.ohos_id_color_primary'))
          .onClick(() => router.pushUrl({ url: 'pages/theme_setting' }))
      }

      .width('100%')

    }
    .height('100%')
    .grayscale(this.gray_mode)
  }
}

AppColor.ets

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

export class AppColors implements CustomColors {
  //自定义品牌色
  brand: ResourceColor = '#FF75D9';
}

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

export let gAppTheme: CustomTheme = new AppTheme()

TestImgToFile.ets

//模拟保存图片获取图片操作
import { util } from '@kit.ArkTS';
import fs from '@ohos.file.fs';
import { BusinessError } from '@kit.BasicServicesKit';
import { GetFileImgUrl } from "./utilToImgSrc"
import { common } from '@kit.AbilityKit';

const base64String =
  'iVBORw0KGgoAAAANSUhEUgAAAB4AAAAtCAMAAACOACuTAAAALVBMVEVMaXE2QU03QE02QU48PEs0Q0s2QU42Qk43QE43QU03QU04P043QE43QVA3QU7fFG+6AAAADnRSTlMAu3fuESKPVd1mzESqM0jcJEgAAACOSURBVHjatZBJEsAgCARV3BP5/3Oj3mdIZZlrF9CMs+Jx2sSKE/7FIEMmzYimRTuisS8aYRWTykA060xDtKipVelhLYiGRU+6WhJdHai1QK+6X6ZeFXYt9rBEOhzosCaqnfHPtO2TfpV0JXOxgXB/v5t7q0PZ1CN66I2+D3460q/lodkgpdjibeNm/fVtLk4YEK1O5uSkAAAAAElFTkSuQmCC';

@Component
export struct TestImgToFile {
  @State imagestr: string = ''

  base64Image() {
    let begin = 'data:image/jpeg;base64,'
    return begin + base64String
  }

  aboutToAppear(): void {
    // this.imagestr = this.base64Image()
  }

  build() {
    Row() {
      if (this.imagestr != "") {
        Image(this.imagestr).width(30).height(30).backgroundColor(Color.Green)
      }
      Button("保存图片").fontColor(Color.Red).onClick(() => {
        this.picture()
      })
      Button("测试获取图片").fontColor(Color.Red).onClick(() => {
        this.getPic()
      })

    }.height('100%').width('100%')
  }

  picture() {
    let that = new util.Base64Helper();
    let result: Uint8Array = that.decodeSync(base64String, util.Type.MIME);
    let buf: ArrayBuffer = result.buffer as ArrayBuffer
    const context: Context = getContext(this);
    const path1: string = context.filesDir + "/pixel.jpg";
    let file = fs.openSync(path1, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);
    fs.write(file.fd, buf).then(async (writeLen) => {
      console.info("write data to file succeed and size is:" + writeLen);
      fs.closeSync(file);
    }).catch((err: BusinessError) => {
      console.info("write data to file failed with error message: " + err.message + ", error code: " + err.code);
    });
  }

  getPic() {
    let context = getContext() as common.UIAbilityContext
    this.imagestr = GetFileImgUrl(context, "pixel.jpg")
  }
}

theme.ets

import { GetFileImgUrl } from './utilToImgSrc'
import { common } from '@kit.AbilityKit'

export default class theme {
  //资源目录,将需要实现主题切换的资源变量存储在这
  //以下图片资源请自行替换
  static isDown = false;
  //是否从下载获取图片
  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_Ico,其他需要请自行修改
  setting_icon: Resource | string = $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) {
    switch (current_mode) {
      case 'normal_mode':
        this.background_color = $r('app.color.background')
        this.text_color = $r('app.color.brown')
        this.phone_icon = $r('app.media.dialer')
        this.market_icon = $r('app.media.shopping')
        this.notes_icon = $r('app.media.notes')
        this.setting_icon = $r('app.media.settings')
        this.camera_icon = $r('app.media.camera')
        this.photos_icon = $r('app.media.gallery')
        this.music_icon = $r('app.media.music')
        this.video_icon = $r('app.media.video')

        break;
      case 'color_mode':

        this.background_color = $r('app.color.color_background')
        this.text_color = $r('app.color.yellow')
        this.phone_icon = $r('app.media.pwcall')
        this.market_icon = $r('app.media.pwshop')
        this.notes_icon = $r('app.media.pwnotes')
        this.setting_icon = $r('app.media.pwsetting')
        this.camera_icon = $r('app.media.pwcamera')
        this.photos_icon = $r('app.media.pwphotos')
        this.music_icon = $r('app.media.pwmusic')
        this.video_icon = $r('app.media.pwvideo')

        break;
      case 'simple_mode':
        this.background_color = $r('app.color.white')
        this.text_color = $r('app.color.black')
        this.phone_icon = $r('app.media.simplicityCall')
        this.market_icon = $r('app.media.simplicityShop')
        this.notes_icon = $r('app.media.simplicityNotes')
        this.setting_icon = $r('app.media.simplicitySetting')
        this.camera_icon = $r('app.media.simplicityCamera')
        this.photos_icon = $r('app.media.simplicityPhotos')
        this.music_icon = $r('app.media.simplicityMusic')
        this.video_icon = $r('app.media.simplicityVideo')
        break;

      default:
        this.current_mode = 'normal_mode'
        this.background_color = $r('app.color.background')
        this.text_color = $r('app.color.brown')
        this.phone_icon = $r('app.media.dialer')
        this.market_icon = $r('app.media.shopping')
        this.notes_icon = $r('app.media.notes')
        this.setting_icon = $r('app.media.settings')
        this.camera_icon = $r('app.media.camera')
        this.photos_icon = $r('app.media.gallery')
        this.music_icon = $r('app.media.music')
        this.video_icon = $r('app.media.video')
        break;
    }
    this.setDownIcon()
  }

  setDownIcon() {
    if (theme.isDown) {
      //请自行处理逻辑
      this.setDownPic(["pixel.jpg"])
    }
  }

  //设置下载图片
  setDownPic(list: string[]) {
    let context = getContext() as common.UIAbilityContext
    let imagestr = GetFileImgUrl(context, list[0])
    this.setting_icon = imagestr
    //后面请根据项目要求自行完善
  }


  //通过不同的主题切换函数更改主题变量,并在外部通过Appstorage实现应用内共享和画面重现渲染
  light_mode() {
    this.font_color = $r('app.color.black')
    this.background_color = $r('app.color.white')
    this.earphone_icon = $r('app.media.ic_device_earphone_hero_filled')
    this.home_icon = $r('app.media.ic_public_home_filled')
    this.picture_icon = $r('app.media.ic_public_picture_filled')
    this.folder_icon = $r('app.media.ic_public_folder_filled')
    this.setDownIcon()
  }

  dark_mode() {
    this.font_color = $r('app.color.white')
    this.background_color = $r('app.color.background')
    this.earphone_icon = $r('app.media.ic_device_earphone_hero')
    this.home_icon = $r('app.media.ic_public_home')
    this.picture_icon = $r('app.media.ic_public_picture')
    this.folder_icon = $r('app.media.ic_public_folder')
  }

  normal_mode() {
    this.current_mode = 'normal_mode'
    this.background_color = $r('app.color.background')
    this.text_color = $r('app.color.brown')
    this.phone_icon = $r('app.media.dialer')
    this.market_icon = $r('app.media.shopping')
    this.notes_icon = $r('app.media.notes')
    this.setting_icon = $r('app.media.settings')
    this.camera_icon = $r('app.media.camera')
    this.photos_icon = $r('app.media.gallery')
    this.music_icon = $r('app.media.music')
    this.video_icon = $r('app.media.video')
    this.setDownIcon()
  }

  color_mode() {
    this.current_mode = 'color_mode'
    this.background_color = $r('app.color.color_background')
    this.text_color = $r('app.color.yellow')
    this.phone_icon = $r('app.media.pwcall')
    this.market_icon = $r('app.media.pwshop')
    this.notes_icon = $r('app.media.pwnotes')
    this.setting_icon = $r('app.media.pwsetting')
    this.camera_icon = $r('app.media.pwcamera')
    this.photos_icon = $r('app.media.pwphotos')
    this.music_icon = $r('app.media.pwmusic')
    this.video_icon = $r('app.media.pwvideo')
    this.setDownIcon()
  }

  simple_mode() {
    this.current_mode = 'simple_mode'
    this.background_color = $r('app.color.white')
    this.text_color = $r('app.color.black')
    this.phone_icon = $r('app.media.simplicityCall')
    this.market_icon = $r('app.media.simplicityShop')
    this.notes_icon = $r('app.media.simplicityNotes')
    this.setting_icon = $r('app.media.simplicitySetting')
    this.camera_icon = $r('app.media.simplicityCamera')
    this.photos_icon = $r('app.media.simplicityPhotos')
    this.music_icon = $r('app.media.simplicityMusic')
    this.video_icon = $r('app.media.simplicityVideo')
    this.setDownIcon()
  }
}

Theme_setting.ets

import theme from '../pages/theme'

@Entry
@Component
struct Theme_setting {
  @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(this.message)
          .fontSize(50)
          .fontColor(this.theme.text_color)
          .fontWeight(FontWeight.Bold)
      }.justifyContent(FlexAlign.Center)
      .width('100%')

      Row() {
        Column() {
          Image(this.theme.phone_icon).objectFit(ImageFit.Contain)
          Text('电话').fontColor(this.theme.text_color)
          Image(this.theme.camera_icon).objectFit(ImageFit.Contain)
          Text('相机').fontColor(this.theme.text_color)
        }.width('22%').height(90)

        Column() {
          Image(this.theme.market_icon).objectFit(ImageFit.Contain)
          Text('商城').fontColor(this.theme.text_color)
          Image(this.theme.photos_icon).objectFit(ImageFit.Contain)
          Text('相册').fontColor(this.theme.text_color)
        }.width('22%').height(90)

        Column() {
          Image(this.theme.notes_icon).objectFit(ImageFit.Contain)
          Text('备忘录').fontColor(this.theme.text_color)
          Image(this.theme.music_icon).objectFit(ImageFit.Contain)
          Text('音乐').fontColor(this.theme.text_color)
        }.width('22%').height(90)

        Column() {
          Image(this.theme.setting_icon).objectFit(ImageFit.Contain)
          Text('设置').fontColor(this.theme.text_color)
          Image(this.theme.video_icon).objectFit(ImageFit.Contain)
          Text('视频').fontColor(this.theme.text_color)
        }.width('22%').height(90)
      }.width('100%').alignItems(VerticalAlign.Top).height('250vp').justifyContent(FlexAlign.SpaceEvenly)

      Row() {
        Button('color mode')
          .width('30%')
          .fontColor(this.theme.text_color)
          .onClick(() => {
            this.message = 'color mode'
            this.theme.color_mode()
            this.current_mode = 'color_mode'
          })
        Button('normal mode')
          .width('30%')
          .fontColor(this.theme.text_color)
          .onClick(() => {
            this.message = 'normal mode'
            this.theme.normal_mode()
            this.current_mode = 'normal_mode'
          })
        Button('simple mode')
          .width('30%')
          .fontColor(this.theme.text_color)
          .onClick(() => {
            this.message = 'simple mode'
            this.theme.simple_mode()
            this.current_mode = 'simple_mode'
          })
      }.height(50)
      .justifyContent(FlexAlign.SpaceAround)
      .width('100%')

      Image($r('app.media.find_service')).objectFit(ImageFit.Contain).height(200)
      Row() {
        Button('gray mode off').fontColor(this.theme.text_color).height('30vp').onClick(() => this.gray_mode = 0)
        Button('gray mode on').fontColor(this.theme.text_color).height('30vp').onClick(() => this.gray_mode = 1)
      }
    }
    .grayscale(this.gray_mode)
    .height('100%').backgroundColor(this.theme.background_color)
  }
}

utilToImgSrc.ets

import { common } from '@kit.AbilityKit';
import { fileUri } from '@kit.CoreFileKit';


export function GetFileImgUrl(context: common.UIAbilityContext, imgStr: string): string {
  let pathDir = context.filesDir;
  let filePath = pathDir + `/${imgStr}`;
  let uri = fileUri.getUriFromPath(filePath);
  return uri;
}
分享
微博
QQ
微信
回复
2天前
相关问题
HarmonyOS 换肤功能怎么实现
728浏览 • 1回复 待解决
如何实现 app 内置全局悬浮球功能
2130浏览 • 1回复 待解决
应用内整体换肤的最佳实践
803浏览 • 1回复 待解决
HarmonyOS 换肤相关指导
94浏览 • 1回复 待解决
HarmonyOS 换肤方案有哪些?
425浏览 • 1回复 待解决
HarmonyOS 全局粘贴的功能
120浏览 • 1回复 待解决
HarmonyOS换肤方案有哪些?
604浏览 • 1回复 待解决
如何实现全局dialog?
552浏览 • 1回复 待解决
HarmonyOS Overlay机制是否支持换肤
25浏览 • 1回复 待解决
HarmonyOS 如何实现全局弹框
291浏览 • 1回复 待解决
全局关闭弹窗如何实现
485浏览 • 2回复 待解决
HarmonyOS 是否有全局粘贴的功能
250浏览 • 1回复 待解决
HarmonyOS 如何实现APP内全局弹窗
602浏览 • 1回复 待解决
HarmonyOS 如何实现全局页面置灰
124浏览 • 1回复 待解决
HarmonyOS 全局loading的菊花如何实现
520浏览 • 1回复 待解决
如何实现全局浮窗效果
1800浏览 • 1回复 待解决