HarmonyOS ArkUI Image 组件完全指南:objectFit、占位图与加载回调

发布时间:2026/7/18 1:46:56

HarmonyOS ArkUI Image 组件完全指南:objectFit、占位图与加载回调 系列鸿蒙 HarmonyOS 6.1 新特性实战 · 第 32 篇图片展示是 App 开发中最常见的需求之一。ArkUI 的 Image 组件提供了 6 种缩放模式objectFit、骨架屏占位方案和完整的加载回调体系几乎覆盖所有图片展示场景。本篇用可运行的代码全面演示这些用法。运行效果初始状态展示 Cover 缩放模式切换到 Fill 完全填充模式一、objectFit 6 种缩放模式objectFit控制图片在容器内的缩放和对齐方式State fitMode: ImageFit ImageFit.Cover Image($r(app.media.startIcon)) .width(200).height(150) .objectFit(this.fitMode) .backgroundColor(#f0f0f0)6 种模式对比模式说明ImageFit.Cover保持比例填满容器超出部分裁剪最常用ImageFit.Contain保持比例完整显示容器可能留空ImageFit.Fill拉伸填满容器不保持比例ImageFit.Auto保持原始尺寸超出裁剪ImageFit.ScaleDown仅缩小不放大取 None 和 Contain 较小者ImageFit.None原始尺寸不缩放const fitModes: ImageFit[] [ ImageFit.Cover, ImageFit.Contain, ImageFit.Fill, ImageFit.Auto, ImageFit.ScaleDown, ImageFit.None ]切换模式Button(下一个) .onClick(() { this.fitIndex (this.fitIndex 1) % this.fitModes.length this.fitMode this.fitModes[this.fitIndex] })二、骨架屏占位图片加载前显示灰色骨架避免布局抖动State showSkeleton: boolean true Stack() { // 实际图片 Image($r(app.media.startIcon)) .width(100%).height(200) .objectFit(ImageFit.Cover) .borderRadius(8) .visibility(this.showSkeleton ? Visibility.Hidden : Visibility.Visible) // 骨架占位 Column() .width(100%).height(200) .backgroundColor(#e8e8e8) .borderRadius(8) .visibility(this.showSkeleton ? Visibility.Visible : Visibility.Hidden) } // 模拟 1.5s 加载完成 .onAppear(() { setTimeout(() { this.showSkeleton false }, 1500) })三、加载回调onComplete / onErrorState loadStatus: string 加载中... State imgWidth: number 0 State imgHeight: number 0 Image($r(app.media.startIcon)) .onComplete((event) { if (event) { this.imgWidth event.width this.imgHeight event.height this.loadStatus 加载成功${event.width}×${event.height} } }) .onError(() { this.loadStatus 图片加载失败 })onComplete回调携带图片的实际像素尺寸可用于计算布局比例。四、网络图片与缓存// 网络图片需在 module.json5 申请 ohos.permission.INTERNET Image(https://example.com/image.jpg) .width(100%).height(200) .objectFit(ImageFit.Cover) // 本地资源推荐 Image($r(app.media.myImage))网络图片默认有缓存同 URL 第二次加载速度快。完整代码Entry Component struct Index { State fitIndex: number 0 State showSkeleton: boolean true State loadInfo: string 等待加载完成 private fitModes: ImageFit[] [ ImageFit.Cover, ImageFit.Contain, ImageFit.Fill, ImageFit.Auto, ImageFit.ScaleDown, ImageFit.None ] private fitNames: string[] [Cover, Contain, Fill, Auto, ScaleDown, None] aboutToAppear(): void { setTimeout(() { this.showSkeleton false }, 1500) } build() { Scroll() { Column({ space: 20 }) { Text(Image 组件完全指南).fontSize(22).fontWeight(FontWeight.Bold).fontColor(#1a1a1a) // objectFit 演示 Column({ space: 10 }) { Text(一、objectFit 缩放模式).fontSize(15).fontWeight(FontWeight.Bold).fontColor(#333) Text(当前 this.fitNames[this.fitIndex]).fontSize(14).fontColor(#0066ff) Image($r(app.media.startIcon)) .width(100%).height(200) .objectFit(this.fitModes[this.fitIndex]) .backgroundColor(#f0f0f0).borderRadius(8) .onComplete((event) { if (event) { this.loadInfo 图片尺寸${event.width} × ${event.height} px } }) Row({ space: 8 }) { Button(上一个).fontSize(12).height(36).backgroundColor(#e8f0ff).fontColor(#0066ff) .onClick(() { this.fitIndex (this.fitIndex - 1 this.fitModes.length) % this.fitModes.length }) Button(下一个).fontSize(12).height(36).backgroundColor(#0066ff).fontColor(#fff) .onClick(() { this.fitIndex (this.fitIndex 1) % this.fitModes.length }) } Text(this.loadInfo).fontSize(12).fontColor(#888) } .padding(12).backgroundColor(#fff).borderRadius(8).width(100%) .border({ width: 1, color: #e0e0e0 }).alignItems(HorizontalAlign.Start) // 骨架屏 Column({ space: 8 }) { Text(二、骨架屏占位).fontSize(15).fontWeight(FontWeight.Bold).fontColor(#333) Stack() { Image($r(app.media.startIcon)) .width(100%).height(150).objectFit(ImageFit.Cover).borderRadius(8) .visibility(this.showSkeleton ? Visibility.Hidden : Visibility.Visible) Column().width(100%).height(150).backgroundColor(#e8e8e8).borderRadius(8) .visibility(this.showSkeleton ? Visibility.Visible : Visibility.Hidden) } Text(this.showSkeleton ? 加载中骨架屏显示中... : 图片加载完成) .fontSize(13).fontColor(this.showSkeleton ? #aaa : #27ae60) } .padding(12).backgroundColor(#fff).borderRadius(8).width(100%) .border({ width: 1, color: #e0e0e0 }).alignItems(HorizontalAlign.Start) } .padding(20).width(100%) } .width(100%).height(100%).backgroundColor(#f5f5f5) } }API 速查属性/方法说明.objectFit(ImageFit.Cover)缩放模式.borderRadius(8)圆角圆形图.borderRadius(size/2).onComplete((event) {...})加载成功回调含 width/height.onError(() {...})加载失败回调$r(app.media.xxx)引用本地资源小结Cover 是首选绝大多数头图/封面图用 Cover自动裁剪保持比例骨架屏用 StackStack Visibility 切换是最简单的骨架方案onComplete 获取尺寸需要动态计算宽高比时利用回调拿实际像素值本地图片用 $r()避免路径错误构建时自动校验资源存在性上一篇Text 组件全解析 | 下一篇Button 组件深度解析类型、状态与自定义样式

相关新闻