这一篇不讲业务逻辑,专门讲“看起来像不像成品”。旅行 App 很吃图片和启动体验:资源命名、图片裁切、渐变遮罩、启动窗口背景和应用内启动页,都会影响用户第一印象。

项目落点:

  • 图片资源:entry/src/main/resources/base/media
  • 启动窗口:entry/src/main/module.json5
  • 启动背景色:entry/src/main/resources/base/element/color.json
  • 应用内启动页:LaunchSplash()
  • 图片展示:ImageFit.Cover、主题色兜底、渐变层

读完这一篇,你可以复用一套离线图片管理思路:图片走资源系统,数据层保存 Resource,UI 层统一裁切和遮罩,启动体验保持前后一致。

本文解决什么

  • 把本地图片放进资源系统,避免页面拼文件路径。
  • 让启动窗口背景、应用内启动页和首屏色调保持一致,减少冷启动跳变。
  • 用主题色、Cover 裁切和渐变遮罩统一不同来源图片的观感。

旅行 App 的一半体验在图片

旅行攻略应用和普通工具应用最大的区别,是图片非常重要。

《疆域纪行》内置了大量本地图片资源:

entry/src/main/resources/base/media/
├── img_kanas.jpg
├── img_sayram.jpg
├── img_duku.jpg
├── img_kashgar_oldtown.jpg
├── img_dapanji.jpg
├── splash_fullscreen.jpg
├── splash_poster.png
├── startIcon.png
└── ...

这些图片覆盖了景点、美食、路线、启动页和图标。对离线 App 来说,本地资源管理就是产品体验的一部分。

图片资源如何引用

在数据层,图片通过 Resource 引用:

image: $r('app.media.img_sayram')

模型中对应字段是:

image: Resource;

这让数据和 UI 之间的关系非常直接。页面组件不需要拼路径,也不需要关心图片文件名,只要消费 item.image

例如卡片里:

Image(item.image)
  .width('100%')
  .height(150)
  .objectFit(ImageFit.Cover)

详情页头图里:

this.DetailHero(item.color, item.image)

这就是把资源引用纳入数据模型的好处。

启动页:不要让冷启动像白屏

项目自己做了应用内启动页:

@State showLaunchSplash: boolean = true;

build() 里先判断:

if (this.showLaunchSplash) {
  this.LaunchSplash()
} else {
  this.MainShell()
}

启动页组件:

@Builder
LaunchSplash() {
  Image($r('app.media.splash_fullscreen'))
    .width('100%')
    .height('100%')
    .objectFit(ImageFit.Cover)
    .backgroundColor('#071D32')
    .onAppear(() => {
      setTimeout(() => {
        this.showLaunchSplash = false;
      }, 1800);
    })
}

这里用一张全屏图片做过渡,1.8 秒后进入主页面。

对内容型 App 来说,启动页有两个作用:

  • 让品牌和场景先出现。
  • 避免图片资源加载时的突兀空白。

不过要注意,应用内启动页不宜过长。用户不是来看广告的,1-2 秒足够。

系统启动窗口配置

除了应用内启动页,module.json5 里还有系统启动窗口配置:

"startWindowIcon": "$media:startIcon",
"startWindowBackground": "$color:start_window_background"

颜色定义在:

{
  "color": [
    {
      "name": "start_window_background",
      "value": "#071D32"
    }
  ]
}

这里的背景色和应用内启动页保持一致。这样从系统启动窗口到 App 首屏,视觉不会跳变。

图片裁切:统一用 Cover

项目中大部分图片展示都使用:

.objectFit(ImageFit.Cover)

它的作用是让图片填满容器,超出部分裁切。

旅行素材的比例经常不同:

  • 景点横图
  • 美食近景
  • 城市街区图
  • 路线封面图

如果直接等比完整显示,卡片高度会不稳定;如果强行拉伸,图片会变形。Cover 是列表卡片和头图里最稳的选择。

用主题色兜底图片观感

许多卡片先放主题色,再叠加图片:

Column()
  .width('100%')
  .height(150)
  .backgroundColor(item.color)

Image(item.image)
  .width('100%')
  .height(150)
  .objectFit(ImageFit.Cover)
  .opacity(0.55)

这样做有三个好处:

  • 图片未加载前不会是纯白空块。
  • 不同图片在透明度叠加后更统一。
  • 文字覆盖在图片上时可读性更好。

尤其是本地素材来源不完全一致时,这种“主题色 + 半透明图片 + 渐变”的组合能快速提升整体一致性。

渐变层保证文字可读

FeatureCard 里有渐变遮罩:

Column()
  .width('100%')
  .height(150)
  .linearGradient({
    angle: 180,
    colors: [['#00000011', 0.0], ['#000000CC', 1.0]]
  })

很多图片上半部分亮、下半部分暗,或者主体颜色复杂。如果直接放文字,白字可能在雪山、湖面、天空上消失。

渐变层的作用不是装饰,而是可读性保障。

详情页头图可以更“沉浸”

详情页头图组件接收颜色和图片:

@Builder
DetailHero(color: string, image: Resource) {
  Stack() {
    Column()
      .width('100%')
      .height(244)
      .backgroundColor(color)
    Image(image)
      .width('100%')
      .height(244)
      .objectFit(ImageFit.Cover)
      .opacity(0.82)
  }
  .height(244)
}

头图比列表图更高,因为详情页的目的不是快速扫读,而是让用户进入一个目的地内容。

旅行类详情页可以大胆使用更高的头图,但要注意两个问题:

  • 内容面板要向上衔接,避免上下割裂。
  • 顶部返回按钮要保证在图片上可见。

图片命名要有规则

项目里的图片基本遵循:

img_地点或内容.jpg

例如:

img_kanas.jpg
img_sayram.jpg
img_kashgar_oldtown.jpg
img_dapanji.jpg
img_laghman.jpg

命名规则看似小事,但资源一多就很重要。建议遵守:

  • 全小写。
  • 单词用下划线。
  • 景点用英文或拼音稳定命名。
  • 不用 1.jpgnew.jpgtest.jpg
  • 启动页、图标单独命名。

后续维护内容库时,资源名能直接对应数据 id,效率会高很多。

离线图片的包体权衡

离线 App 的图片都随包发布,因此要关注包体积。

这个项目的素材单张图片大多在几十 KB 到几百 KB 之间,适合 MVP。后续如果内容扩展到数百张图片,需要考虑:

  • 压缩 JPG 质量。
  • 控制图片尺寸,不要直接放超大原图。
  • 区分缩略图和详情图。
  • 对路线、城市复用同一张封面。
  • 后续版本考虑可选离线包下载。

图片越多,越要避免“每个页面都上一张 2MB 原图”的做法。

场景 推荐资源策略 原因
首页卡片 中等尺寸 JPG 列表多图,优先控制加载压力
详情头图 较高清封面 用户停留时间长,视觉收益高
启动页 单张压缩图 避免冷启动阶段等待过久
商店截图 单独导出 PNG/JPEG 不和应用运行资源混在一起

离线 App 的图片策略要同时考虑视觉和包体。素材不是越大越好,而是要匹配显示位置。

验证清单

检查项 操作方式 通过标准
所有 Markdown 配图都是本地 PNG 对照项目文件或真机/模拟器操作 结果符合文章描述
App 图片资源都能通过 $r 引用 对照项目文件或真机/模拟器操作 结果符合文章描述
启动背景色和启动页主色一致 对照项目文件或真机/模拟器操作 结果符合文章描述
卡片图片使用固定容器和 Cover 对照项目文件或真机/模拟器操作 结果符合文章描述
图片上文字有遮罩保证可读 对照项目文件或真机/模拟器操作 结果符合文章描述

常见问题和处理

问题现象 优先排查 处理方式
启动瞬间白屏明显 检查 startWindowBackground 应用内启动页背景色要一致
图片被拉伸 检查是否使用 Cover 不要只给宽度不给高度
包体积增长快 检查图片尺寸和质量 缩略图与详情图可分层管理

本篇小结

资源与图片体验的关键点:

  • 图片资源通过 $r('app.media.xxx') 引用。
  • 数据模型直接保存 Resource
  • 系统启动窗口和应用内启动页保持色彩一致。
  • 图片展示统一使用 ImageFit.Cover
  • 主题色和渐变层用于提高视觉一致性和文字可读性。
  • 图片命名要规则化,为后续扩展做准备。

下一篇我们看适配和质量:如何处理长文案、空状态、固定栏遮挡、平板设备和可发布前的视觉稳定性。

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐