一、资源文件是啥

开发鸿蒙应用,肯定得用颜色、字体、间距、图片这些东西。不同设备上这些资源的值可能不一样,比如手机上字号小点,平板上字号大点;深色模式下背景黑点,浅色模式下背景白点。

处理这些差异有两种方式:

应用资源:自己在应用里定义资源,自己管理不同设备或配置下的表现。比如定义一个颜色,手机上红色,平板上蓝色。

系统资源:直接用系统预置的资源定义,也叫分层参数。同一个资源ID在不同设备类型、深浅色配置下有不同取值。

二、应用资源咋组织

应用开发里用的各类自定义资源文件,都放在不同模块的 resources 目录下,方便管理和维护。

resources 目录包括两大类目录:

第一类base 目录和限定词目录。base 目录默认就存在,限定词目录得自己创建。限定词目录的名字可以用一个或多个表征应用场景或设备特征的限定词组合而成。

第二类rawfile 目录,放原始文件。这玩意儿不会根据设备状态去匹配不同资源,所以不在本文讨论范围内。

entry 模块为例,基础目录结构长这样:

└──entry/src/main/resources                                  // 资源区
   ├──base                                                   // 默认存在的目录                                
   │  ├──element       
   │  │  ├──color.json                                       // 颜色资源
   │  │  ├──float.json                                       // 数字资源
   │  │  └──string.json                                      // 字符串资源
   │  ├──media                                               // 媒体资源
   │  └──profile                                             // 路由资源
   ├──en_US                                                  // 限定词目录示例,需要开发者自行创建 
   ├──zh_CN                                                  // 限定词目录示例,需要开发者自行创建 
   └──rawfile                                                // 原始文件目录

应用使用某资源时,系统会根据当前设备状态优先从相匹配的限定词目录中寻找该资源。只有当 resources 目录中没有与设备状态匹配的限定词目录,或者在限定词目录中找不到该资源时,才会去 base 目录中查找。

所以强烈建议所有应用自定义资源都在 base 目录中定义默认值,防止出现找不到资源值的异常场景。

三、资源组目录有哪些

base 目录与限定词目录下面可以创建资源组目录,用于存放特定类型的资源文件。

element 目录

表示元素资源,每一类数据都用相应的 JSON 文件来表征:

  • boolean:布尔型
  • color:颜色
  • float:浮点型
  • intarray:整型数组
  • integer:整型
  • pattern:样式
  • plural:复数形式
  • strarray:字符串数组
  • string:字符串

element 目录中的文件名称建议与下面的文件名保持一致,每个文件中只能包含同一类型的数据:

  • boolean.json
  • color.json
  • float.json
  • intarray.json
  • integer.json
  • pattern.json
  • plural.json
  • strarray.json
  • string.json

element 目录的各个资源文件中,以 “name-value” 的形式定义资源:

// color.json 
{
    "color": [
        {
            "name": "color_red",
            "value": "#FFFF0000"
        },
        {
            "name": "color_blue",
            "value": "#FF0000FF"
        }
    ]
}

media 目录

表示媒体资源,包括图片、音频、视频等非文本格式的文件。

文件名可自定义,比如 icon.png

media 目录中,直接以文件名作为 name,开发者把文件放入 media 目录即可,无需再额外定义 name

四、应用资源咋访问

在工程中,通过 "$r('app.type.name')" 的形式引用应用资源。

  • app:代表应用模块内 resources 目录中定义的资源
  • type:代表资源类型,可以取 colorfloatstringpluralmedia
  • name:代表资源命名,由开发者添加资源时确定

举个例子:

在应用模块的 resources 目录下,创建名为 tablet 的限定词子目录,并在 base 目录和 tablet 限定词目录中添加相应资源:

资源名称 资源类型 base 目录中资源值 限定词目录(tablet)中资源值
my_string string default tablet
my_color color #ff0000 #0000ff
my_float float 60vp 80vp
my_image media my_image.png(太阳图标) my_image.png(月亮图标)

代码中使用:

@Entry
@Component
struct ResourceQualifier {
  build() {
    Column() {
      Text($r('app.string.my_string'))
        .fontSize(60)
        .fontColor($r('app.color.my_color'))
      Image($r('app.media.my_image'))
        .width(100)
        .height(100)
    }
    .height('100%')
    .width('100%')
    .alignItems(HorizontalAlign.Center)
    .justifyContent(FlexAlign.Center)
  }
}

运行效果:

默认设备上,显示 “default”、红色文字、太阳图标。

平板上,显示 “tablet”、蓝色文字、月亮图标。

同一资源在不同设备上取值不同,这就是资源限定词的威力。

五、系统资源咋用

除了自定义资源,开发者也可以使用系统中预定义的资源,即分层参数。同一资源ID在设备类型、深浅色等不同配置下有不同的取值。

在开发过程中,分层参数的用法与资源限定词基本一致。开发者可以通过 "$r('sys.type.resource_id')" 的形式引用系统资源。

  • sys:代表系统资源
  • type:代表资源类型,值可以取 colorfloatstringmedia
  • resource_id:代表资源id

注意啊,仅声明式开发范式支持使用分层参数,类Web开发范式不支持。

系统资源可以保证不同团队开发出的应用有较为一致的视觉风格。对于系统预置应用,强烈建议使用系统资源;对于三方应用,可以根据需要选择使用系统资源或自定义应用资源。

六、避坑指南

坑1:base 目录忘定义默认值

我就踩过这个坑。在限定词目录里定义了资源,但忘了在 base 目录定义默认值。结果在某个设备上运行时,直接报错找不到资源。

咋解决?所有应用自定义资源都在 base 目录中定义默认值,哪怕限定词目录里有值,base 目录也得有默认值兜底。

坑2:限定词目录命名不规范

限定词目录的名字有讲究,不能随便起。比如想匹配平板设备,限定词目录名应该是 tablet,不是 padtablet_device

如果不按规范命名,系统匹配不到对应目录,就会回退到 base 目录查找资源。

坑3:资源类型搞混了

element 目录下,不同类型的资源要放在对应的 JSON 文件里。比如颜色资源放 color.json,字符串资源放 string.json

我有一次把颜色资源写到 string.json 里,结果取值的时候取不到,折腾半天才发现文件写错了。

坑4:media 目录文件命名不规范

media 目录下,文件名直接作为资源名使用。文件名不能用中文、空格、特殊字符,建议用小写字母、数字、下划线组合。

比如 my_icon.png 可以,我的图标.png 不行,my icon.png 也不行。

坑5:系统资源 ID 写错

系统资源的 ID 是固定的,写错了会报错。建议先查阅系统资源列表,确认 ID 正确后再使用。

坑6:限定词匹配优先级搞不清

系统匹配限定词目录时,有优先级规则。设备状态可能与多个限定词目录匹配时,系统会选择匹配度最高的那个。

比如 tablet 目录匹配平板设备,zh_CN 目录匹配中文简体语言环境,tabletzh_CN 同时存在时,哪个优先级更高?

这个问题涉及限定词目录的命名规则和匹配规则,建议详细阅读官方文档,搞清楚优先级再动手。

七、总结

资源文件这玩意儿,用好了能大大简化多设备适配工作。

应用资源方面,记住三个关键点:

base 目录必须有,定义默认值兜底。

限定词目录按规范命名,匹配不同设备状态。

资源组目录分类型,element 放文本资源,media 放媒体资源。

系统资源方面,记住两点:

声明式开发范式支持,类Web开发范式不支持。

引用方式 $r('sys.type.resource_id'),与应用资源引用方式类似。

最后,资源文件不是万能的,有些场景还是得用代码逻辑判断设备状态。但能用资源文件解决的,尽量用资源文件,代码更简洁,维护更方便。

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐