目录

如何跟随系统深/浅色模式获取对应的资源文件

问题现象

深色模式下获取dark目录下的资源,浅色模式下获取base目录下的资源。

效果预览

背景知识

resourceManager.getResourceManager获取的资源的配置(语言、深浅色、分辨率、横竖屏等)是由系统决定的,而通过getOverrideResourceManager接口返回的对象,应用可以获取符合指定配置的资源,即差异化资源,比如在浅色模式时可以获取深色资源。

解决方案

根据系统配置获取对应图片并绘制到界面,示例代码如下:

import { ConfigurationConstant, Context } from '@kit.AbilityKit';
import { image } from '@kit.ImageKit';

export class Point {
  x: number = 0;
  y: number = 0;

  set(x: number, y: number) {
    this.x = x;
    this.y = y;
  }
}

@Entry
@Component
struct GetResource {
  private settings: RenderingContextSettings = new RenderingContextSettings(true);
  private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings);
  hostContext = this.getUIContext().getHostContext()?.getApplicationContext();
  isDarkMode: boolean = false;
  mCircleBg: image.PixelMap | undefined = undefined;
  centerPoint = new Point();

  // 获取资源并转化为PixelMap
  image2PixelMap(context: Context, resource: Resource) {
    // 获取对应系统颜色模式配置下的资源管理器
    let overrideResMgr = context.resourceManager.getOverrideResourceManager();
    let data = overrideResMgr.getMediaContentSync(resource.id);

    let arrayBuffer = data.buffer.slice(data.byteOffset, data.byteLength + data.byteOffset);
    let imageSource: image.ImageSource = image.createImageSource(arrayBuffer);
    let value = imageSource.getImageInfoSync();
    let opts: image.DecodingOptions = {
      editable: true,
      desiredSize: {
        height: value.size.height,
        width: value.size.width
      }
    };
    return imageSource.createPixelMapSync(opts);
  }

  // 清除并绘制图片
  draw() {
    this.mCircleBg = this.image2PixelMap(this.hostContext as Context, $r('app.media.theme_joystick_big_circle_bg'));
    this.context.clearRect(-this.centerPoint.x, -this.centerPoint.y, this.centerPoint.x * 2, this.centerPoint.y * 2);
    let innerR = 150;
    this.context.drawImage(this.mCircleBg, -innerR, -innerR, innerR * 2, innerR * 2);
  }

  build() {
    Column() {
      Text('适配颜色(点我切换)')
        .fontColor($r('app.color.text_primary'))
        .fontSize(24)
        .margin({ top: 100 })
        .onClick(() => {
          if (this.isDarkMode) {
            this.hostContext?.setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_LIGHT);
            this.isDarkMode = false;
            this.draw();
          } else {
            this.hostContext?.setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_DARK);
            this.isDarkMode = true;
            this.draw();
          }
        })
      Column() {
        Canvas(this.context)
          .width('100%')
          .height('100%')
          .onReady(() => {
            let measuredWidth = this.context.width;
            let measuredHeight = this.context.height;
            this.centerPoint.set(measuredWidth / 2, measuredHeight / 2);
            this.context.clearRect(-this.centerPoint.x, -this.centerPoint.y, this.centerPoint.x * 2,
              this.centerPoint.y * 2);
            this.context.translate(this.centerPoint.x, this.centerPoint.y);
            this.draw();
          })
      }
      .width('100%')
      .height('auto')
    }
    .height('100%')
    .padding({ left: 16, right: 16 })
    .width('100%')
    .backgroundColor($r('app.color.bg_primary'))
    .expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP, SafeAreaEdge.BOTTOM])
  }
}

常见FAQ

Q:为什么context.resourceManager只能获取LIGHT模式下的资源?

A:当前接口获取系统资源管理ResourceManager对象中的Configuration为默认值,颜色模式默认是LIGHT。