HarmonyOS应用开发实战:猫猫大作战-`$r` 与 `$rawfile` 的区别、资源目录结构、多分辨率适配

HarmonyOS应用开发实战:猫猫大作战-`$r` 与 `$rawfile` 的区别、资源目录结构、多分辨率适配
前言前面我们大量用 Emoji、、做图标——简单但不专业。真正的游戏需要 PNG/JPG/SVG 图集猫咪精灵图、UI 图标、背景插画。HarmonyOS 加载图片资源有两条路径——$r()引用编译期资源和**$rawfile()引用原始文件**。两者用法、性能、适用场景完全不同。本篇以「猫猫大作战」图标资源加载为锚点把$r与$rawfile的区别、资源目录结构、多分辨率适配三大要点讲透。提示本系列不讲 ArkTS 基础语法与环境搭建假设你已跟完第 1–26 篇。本篇是布局进阶的第七篇。一、场景拆解图标资源加载回顾「猫猫大作战」主菜单标题图标第 1 篇// 来源entry/src/main/ets/pages/Index.ets MainMenuView() Text().fontSize(72)这是用 Emoji 文字做图标。现在想换成专业的 PNG 图标cat_logo.png——需要 Image 组件 资源引用// 写法 1$r() 引用编译期资源推荐 Image($r(app.media.cat_logo)) .width(72).height(72) // 写法 2$rawfile() 引用原始文件 Image($rawfile(icons/cat_logo.png)) .width(72).height(72)关键区别维度$r(app.media.xxx)$rawfile(path/xxx)资源位置resources/base/media/resources/rawfile/编译处理编译期索引、可多语言多分辨率原样打包不处理引用方式资源名无扩展名相对路径含扩展名适用UI 图标、标准图片动效 JSON、字体、大文件二、$r 编译期资源引用2.1 资源目录结构entry/src/main/resources/ ├─ base/ # 默认资源所有设备匹配 │ ├─ element/ # string.json, color.json, float.json │ ├─ media/ # 图片、音频、视频 │ │ ├─ cat_logo.png │ │ ├─ icon_pause.png │ │ └─ bg_main.jpg │ └─ profile/ # 自定义 JSON 配置 ├─ zh_CN/element/ # 中文语言覆盖 ├─ en_US/element/ # 英文语言覆盖 ├─ dark/element/ # 暗色模式覆盖 └─ rawfile/ # 原始文件不编译 └─ icons/cat_logo.png2.2 $r 三种资源类型// 1. media图片/音频/视频 Image($r(app.media.cat_logo)) // 2. string字符串 Text($r(app.string.hello_world)) // 3. color/float颜色/尺寸 Text(A).fontColor($r(app.color.primary)) Text(B).fontSize($r(app.float.title_size))关键经验$r(app.type.name)引用资源——type是media/string/color/float/plural等name是资源名不含扩展名。2.3 命名规则// ✅ 合法资源名 $r(app.media.cat_logo) // 蛇形命名 $r(app.media.icon_pause) $r(app.string.hello_world) // ❌ 非法资源名 $r(app.media.catLogo) // 驼峰ArkTS 不允许 $r(app.media.cat-logo) // 含连字符 $r(app.media.cat logo) // 含空格提示HarmonyOS 资源名必须蛇形命名snake_case——驼峰会编译报错。2.4 多分辨率适配HarmonyOS 自动按设备密度加载对应 dpi 的图片resources/ ├─ base/media/cat_logo.png # 默认mdpi 1x ├─ fiberscale-2x/media/cat_logo.png # 2x 高分辨率 └─ fiberscale-3x/media/cat_logo.png # 3x 超高分辨率设备密度加载的图片mdpi1xbase/media/cat_logo.pngxhdpi2xfiberscale-2x/media/cat_logo.pngxxhdpi3xfiberscale-3x/media/cat_logo.png实战经验UI 图标准备 1x、2x、3x 三套——分别放在base/media、fiberscale-2x/media、fiberscale-3x/media系统自动选最清晰的。三、$rawfile 原始文件引用3.1 适用场景// 1. Lottie 动效 JSON Image($rawfile(lottie/loading.json)) // 2. 自定义字体 TTF Font().registerFont({ familyName: Custom, familySrc: $rawfile(fonts/Custom.ttf) }) // 3. 大型背景图不想编译处理 Image($rawfile(bg/level_1.jpg)) // 4. 配置 JSON 文件 const config fs.readSync($rawfile(config/game.json))3.2 路径规则$rawfile(icons/cat_logo.png) // 相对 resources/rawfile/ 的路径 // 完整路径resources/rawfile/icons/cat_logo.png关键经验$rawfile路径必须包含扩展名——与$r省略扩展名不同。3.3 $rawfile vs $r 的核心差异维度$r$rawfile编译期索引✅ 拼写错误编译报错❌ 运行时才报错多语言覆盖✅zh_CN//en_US/自动切❌ 不支持多分辨率✅fiberscale-2x/自动选❌ 不支持暗色模式✅dark/自动切❌ 不支持文件类型限制限图片/音频/视频任意文件适用UI 图标、标准化资源Lottie、字体、大文件实战经验能用 $r 就用 $r——编译期校验、多端适配都免费。只有 Lottie 动效、自定义字体这种「非标准资源」才用 $rawfile。四、用 $r 改造主菜单图标4.1 替换标题 Emoji 为 PNG 图标假设已放置resources/base/media/cat_logo.pngBuilder MainMenuView() { Column() { Spacer().height(15%) // 改造Emoji → $r PNG 图标 Image($r(app.media.cat_logo)) .width(72) .height(72) .margin({ bottom: 8 }) Text(猫猫大作战).fontSize(36).fontWeight(FontWeight.Bold).fontColor(#2C3E50).margin({ bottom: 8 }) Text(合并进化 · 策略消除).fontSize(16).fontColor(#95A5A6).margin({ bottom: 48 }) if (this.highScore 0) { Row() { // 改造 Emoji → $r PNG 奖杯图标 Image($r(app.media.icon_trophy)) .width(20).height(20) Text( 最高分: ${this.highScore}).fontSize(16).fontColor(#F1C40F).fontWeight(FontWeight.Bold) }.margin({ bottom: 32 }) } // 开始游戏按钮 Button(开始游戏) .width(70%).height(56) .fontSize(20).fontWeight(FontWeight.Bold) .fontColor(#FFFFFF).backgroundColor(#2ECC71) .borderRadius(28) .shadow({ radius: 8, color: rgba(46, 204, 113, 0.4), offsetY: 4 }) .onClick(() { this.startGame(); }) Spacer().height(24) // 规则面板第 25 篇 Scroll() { /* ... */ }.height(180) Spacer() } .width(100%).height(100%) .linearGradient({ direction: GradientDirection.Bottom, colors: [[#E8F4F8, 0.0], [#D6EEF5, 0.5], [#C9E8F2, 1.0]] }) .alignItems(HorizontalAlign.Center) }4.2 Image 组件常用属性Image($r(app.media.cat_logo)) .width(72).height(72) // 尺寸 .objectFit(ImageFit.Contain) // 缩放模式 .borderRadius(12) // 圆角 .interpolation(ImageInterpolation.High) // 高质量插值 .draggable(false) // 禁止拖拽 .alt($r(app.media.placeholder)) // 加载失败占位图4.3 objectFit 缩放模式ImageFit 值效果适用Contain等比缩放完整显示可能留白UI 图标推荐Cover等比缩放填满容器可能裁剪背景图Fill拉伸填满变形不推荐None原始尺寸可能溢出精确像素ScaleDown等比缩小不放大缩略图实战经验UI 图标用 Contain——保证图标完整不变形全屏背景用 Cover——填满屏幕不裁剪主体。五、资源访问的编程式 API5.1 resourceManager 获取资源import { common } from kit.AbilityKit; const context getContext(this) as common.UIAbilityContext; const resMgr context.resourceManager; // 同步获取字符串 const str: string resMgr.getStringSync($r(app.string.hello_world).id); // 同步获取颜色 const color: number resMgr.getColorSync($r(app.color.primary).id); // 异步获取 rawfile 文件描述符 const rawFd await resMgr.getRawFd(config/game.json); // rawFd { fd, offset, length }5.2 getStringByNameSync 按名取值// 按资源名不含 app. 前缀取字符串 const greeting: string resMgr.getStringByNameSync(hello_world);实战经验UI 层用$r()直接渲染逻辑层用resourceManager取值——例如要把字符串塞进 ArrayBuffer 时。六、踩坑提示6.1 资源名拼错// ❌ 错误拼写错误编译报错 Image($r(app.media.cat_Logo)) // L 大写 Image($r(app.media.catlogo)) // 缺下划线 // ✅ 正确与文件名完全一致蛇形 Image($r(app.media.cat_logo))6.2 $r 引用 rawfile 资源// ❌ 错误$r 不能引用 rawfile 下的文件 Image($r(app.media.cat_logo)) // 但 cat_logo.png 在 rawfile/icons/ 下 // ✅ 正确rawfile 用 $rawfile Image($rawfile(icons/cat_logo.png))6.3 多分辨率图片缺失# ❌ 只有 3x 图1x 设备加载 3x 图缩放模糊 resources/base/media/ # 空 resources/fiberscale-3x/media/cat_logo.png # ✅ 至少提供 1x 和 3x resources/base/media/cat_logo.png # 1x resources/fiberscale-3x/media/cat_logo.png # 3x6.4 Image 不设宽高// ❌ 错误不设尺寸Image 按图片原始像素渲染可能撑爆屏幕 Image($r(app.media.cat_logo)) // ✅ 正确显式设尺寸 Image($r(app.media.cat_logo)).width(72).height(72)七、调试技巧DevEco 资源预览resources/base/media/下的图片在 IDE 里直接预览。console.info打资源 id$r(app.media.cat_logo).id打 log追资源加载。图片不显示排查检查资源名拼写检查文件是否在media/或rawfile/检查 Image 宽高是否设。模糊排查1x 设备加载 3x 图会缩放模糊补全多分辨率资源。八、性能与最佳实践UI 图标用 $r——编译期校验、多分辨率适配免费。**Lottie/字体/大文件用rawfile**——r 不支持非标准资源。资源名蛇形命名——驼峰会编译报错。多分辨率准备 1x/2x/3x——避免高 dpi 设备加载低清图模糊。Image 必须设宽高——不设按原始像素渲染可能撑爆屏幕。UI 图标 objectFit 用 Contain——保证完整不变形。总结本篇我们从 Image 资源引用切入掌握了**r 编译期资源多语言/多分辨率/暗色自动适配**、**rawfile 原始文件Lottie/字体/大文件、资源目录结构与命名规则三大要点并给出了主菜单 PNG 图标改造完整代码。核心要点r 编译期校验多端适配rawfile 任意文件资源名蛇形命名UI 图标准备 1x/2x/3x 三套**。下一篇我们将拆解暗色模式适配——深色资源与 colorMode。如果这篇文章对你有帮助欢迎点赞、收藏⭐、关注你的支持是我持续创作的动力相关资源「猫猫大作战」项目源码本仓库entry/src/main/ets/pages/Index.etsImage 组件官方指南资源引用 $r 与 $rawfile 官方指南资源目录结构官方文档多分辨率资源适配最佳实践开源鸿蒙跨平台社区HarmonyOS 开发者官方文档首页系列索引本仓库articles/INDEX.md