> 技术文档 > 鸿蒙如何适配2x、3x不同密度的切图_鸿蒙2x 3x切图资源管理

鸿蒙如何适配2x、3x不同密度的切图_鸿蒙2x 3x切图资源管理


本文同步发表于我的微信公众号,微信搜索 程语新视界 即可关注,每个工作日都有文章更新

鸿蒙(HarmonyOS)应用开发中,资源分类与访问是适配多设备、多场景的核心机制。以下是详细的分类说明和访问示例:

一、资源分类

鸿蒙资源文件按存储位置和用途分为以下类型:

1. 基础资源目录
  • base目录 默认存在的目录,存放通用资源。子目录包括:
    • element:字符串、颜色、布尔值等基础元素(如string.jsoncolor.json)。
    • media:图片、音频等媒体文件(如icon.png)。
    • profile:动画、布局等配置文件(如test_profile.json) 。
2. 限定词目录
  • 命名规则: 由语言、屏幕方向、设备类型等限定词组合命名,例如:
    • zh_CN(简体中文)
    • en_GB-vertical-car-mdpi(英式英语+竖屏+车机+中密度屏幕) 。
  • 匹配优先级: 系统会根据设备特征自动匹配最接近的限定词目录,未找到则回退到base目录。
3. 原始文件目录
  • rawfile: 文件保持原始格式,不编译不压缩,通过路径直接访问(如$rawfile(\'test.png\')) 。
     
  • resfile: 类似rawfile,但安装后解压到应用沙箱,通过Context.resourceDir获取路径访问。

二、资源访问方式

1. 编译型资源访问

通过$r(\'app.type.name\')格式引用,其中:

  • app:表示base或限定词目录。
  • type:资源类型(stringcolormedia等)。
  • name:资源名称(对应JSON中的name字段)。

示例代码

// 引用字符串和颜色资源Text($r(\'app.string.hello\')) // 从string.json中读取 .fontColor($r(\'app.color.primary\')) // 从color.json中读取 .fontSize($r(\'app.float.font_size\')) // 从float.json中读取// 引用图片资源Image($r(\'app.media.icon\')) // 从media目录加载图片// 带参数的多语言字符串Text($r(\'app.string.welcome\', \"用户\")) // 替换string.json中的%s

JSON文件示例resources/base/element/string.json):

{ \"string\": [ { \"name\": \"hello\", \"value\": \"你好\" }, { \"name\": \"welcome\", \"value\": \"欢迎%s\" } ]}
2. 原始文件访问

通过$rawfile或文件API直接访问路径:

// 引用rawfile目录下的图片Image($rawfile(\'images/background.png\'))// 访问resfile目录(需沙箱路径)let context = getContext() as common.UIAbilityContext;let resFilePath = context.resourceDir + \'/resfile/config.json\';
3. 系统资源访问

直接使用预置资源ID(需查阅系统资源表):

Text($r(\'sys.string.APP_NAME\')) // 系统应用名称 .fontColor($r(\'sys.color.ohos_id_color_foreground\')) // 系统前景色

三、多设备适配示例

场景:为手机和车机适配不同图标
  1. 目录结构
resources|---base| |---media| |---icon.png // 默认图标|---en_GB-car-mdpi| |---media| |---icon.png // 车机专用图标

       代码调用

Image($r(\'app.media.icon\')) // 自动匹配设备类型

当设备为车机时,优先加载en_GB-car-mdpi/media/icon.png。

四、屏幕密度与切图适配规则

        为不同屏幕密度(如2x、3x)提供适配的切图是保证多设备显示效果的关键

1. 屏幕密度分类
设备类型 屏幕密度(dpi) 切图目录后缀 典型设备 低密度屏幕(ldpi) 0-120dpi mdpi 部分车机屏幕 中密度屏幕(mdpi) 120-160dpi mdpi 标准手机(旧机型) 高密度屏幕(hdpi) 160-240dpi hdpi 主流手机(如华为P40) 超高密度(xhdpi) 240-320dpi xhdpi 高端手机(2x屏) 超超高密度(xxhdpi) 320-480dpi xxhdpi 旗舰手机(3x屏,如Mate 50)
2. 切图目录命名规则

resources 目录下按密度创建子目录:

resources├── base│ └── media│ └── icon.png # 默认切图(1x基准图)├── hdpi│ └── media│ └── icon.png # 1.5x切图(hdpi)├── xhdpi│ └── media│ └── icon.png # 2x切图(xhdpi)└── xxhdpi └── media └── icon.png # 3x切图(xxhdpi)

3、实际开发示例

场景:为不同密度屏幕提供适配图标
  1. 准备切图文件

    • 基准图base/media/icon.png(100×100px,1x)
    • 2x切图xhdpi/media/icon.png(200×200px)
    • 3x切图xxhdpi/media/icon.png(300×300px)
  2. 代码中引用资源

Image($r(\'app.media.icon\')) // 自动匹配设备密度 .width(100)  // 逻辑像素单位(实际显示大小由系统自动缩放) .height(100)

    3.系统自动匹配流程

 

4、验证适配效果

1. 手动指定密度测试

module.json5 中强制指定屏幕密度进行测试:

{ \"deviceTypes\": [\"phone\", \"tablet\"], \"abilities\": [ { \"name\": \"EntryAbility\", \"screenDensity\": \"xxhdpi\" // 强制使用3x资源 } ]}
2. 动态获取当前密度

通过 display 模块获取实际屏幕信息:

import display from \'@ohos.display\';let displayInfo = display.getDefaultDisplaySync();console.log(`当前屏幕密度: ${displayInfo.densityDPI}dpi`);// 输出示例: 当前屏幕密度: 480dpi(3x设备)

五、高级适配技巧

1. SVG矢量图适配(推荐)
  • 优势:单文件适配所有密度,无需多套切图
  • 实现方法
    Image($r(\'app.media.vector_icon\')) // 引用resources/base/media/vector_icon.svg .width(100) .height(100)
2. 代码控制缩放比例

根据密度动态调整显示大小:

// 计算实际显示尺寸(以1x为基准)function getScaledSize(baseSize: number): number { let density = display.getDefaultDisplaySync().densityDPI / 160; // 160为mdpi基准 return baseSize * density;}Image($r(\'app.media.icon\')) .width(getScaledSize(100)) // 在3x设备上实际渲染为300px .height(getScaledSize(100))
3. 多语言+多密度组合适配

目录结构示例(英文+3x屏):

resources└── en_GB-xxhdpi └── media └── icon.png # 英文环境的3x切图

六、注意事项

  1. 文件层级限制: elementmedia等资源组目录下不能创建子目录,否则编译报错 。
  2. 资源ID生成规则: 非rawfile资源会被编译为二进制,ID由typename组合生成 。
  3. 多工程资源管理: Stage模型下,公共资源需放在AppScope/resources目录
  4. 切图命名一致性:所有密度目录中的同名切图必须保持相同语义(如都是“首页图标”)。
  5. 兜底策略:确保 base 目录存在默认切图,避免匹配失败时无图显示。
  6. 内存优化:3x切图体积较大,避免在列表项等高频场景滥用。