74.HarmonyOS NEXT ImageItemView组件深度剖析:组件底子结构与核心状态管

[复制链接]
发表于 2025-3-16 10:15:01 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
温馨提示:本篇博客的具体代码已发布到 git : https://gitcode.com/nutpi/HarmonyosNext 可以下载运行哦!
  

HarmonyOS NEXT ImageItemView组件深度剖析:组件底子结构与核心状态管理(一)


  
一、组件底子结构剖析


  • 组件装饰器与复用机制
  1. @Reusable
  2. @Component
  3. export struct ImageItemView {
  4.   // ...
  5. }
复制代码


  • @Component:声明这是一个自界说组件,HarmonyOS 中全部 UI 组件必须使用此装饰器
  • @Reusable:实现组件复用机制,当组件被移除时会进入复用缓存池,下次创建时直接复用(类似 Android RecyclerView 的回收机制)
  • 复用场景:在多图切换时,不同图片项可复用同一组件实例,提拔性能

  • 组件生命周期 - aboutToAppear
  1. aboutToAppear(): void {
  2.   this.initCurrentImageInfo(); // 初始化图片信息
  3. }
复制代码


  • 组件即将体现时触发
  • 此处用于初始化图片信息(尺寸、宽高比等),确保组件体现时数据停当
二、核心状态管理


  • 状态变量装饰器
  1. @Consume private bgc: Color;          // 共享背景色
  2. @Link isEnableSwipe: boolean;         // 控制滑动切换
  3. @State isEnableOffset: boolean = false; // 位移开关
  4. @State imageScaleInfo: ScaleModel;    // 缩放状态
  5. @State imageOffsetInfo: OffsetModel;  // 位移状态
复制代码


  • @Consume:跨组件共享状态(与祖先组件的 @Provide 配对使用),这里用于全局背景色管理
  • @Link:父子组件双向绑定,isEnableSwipe 控制是否答应滑动切换图片
  • @State:组件内部状态管理,变化时会触发 UI 更新
  • 计划头脑:通过装饰器实现状态分层管理(全局共享、组件间通信、组件内部状态)

  • 图片信息初始化流程
  1. initCurrentImageInfo(): void {
  2.   const imageSource = image.createImageSource(this.imageUri);
  3.   imageSource.getImageInfo().then((data) => {
  4.     // 计算宽高比和默认尺寸
  5.     this.imageWHRatio = data.size.width / data.size.height;
  6.     this.imageDefaultSize = this.calcImageDefaultSize(...);
  7.     // 判断适配方向(宽度优先/高度优先)
  8.     this.fitWH = this.imageDefaultSize.width === windowWidth ? "width" : "height";
  9.   });
  10.   // 创建像素地图用于显示
  11.   imageSource.createPixelMap().then((data) => {
  12.     this.imagePixelMap = data;
  13.   });
  14. }
复制代码


  • 关键步调:

    • 通过 URI 创建 ImageSource 获取图片元数据
    • 盘算图片默认体现尺寸(根据屏幕宽高比)
    • 异步加载 PixelMap 数据(克制阻塞主线程)

  • 核心算法:calcImageDefaultSize

    • 比较图片与屏幕宽高比,决定按宽度或高度适配
    • 示例:竖屏手机体现横屏图片时,按宽度适配克制上下黑边

三、图片体现核心逻辑

  1. Image(this.imagePixelMap)
  2.   .width(this.fitWH === "width" ? $r(...) : undefined)
  3.   .height(this.fitWH === "height" ? $r(...) : undefined)
  4.   .aspectRatio(this.imageWHRatio)
  5.   .objectFit(ImageFit.Cover)
复制代码


  • 动态尺寸策略:

    • 仅设置宽度或高度,通过 aspectRatio 主动盘算另一维度
    • $r("app.string...") 引用资源文件中的尺寸值(实现多设备适配)

  • objectFit 详解:

    • ImageFit.Cover:保持宽高比缩放,使图片至少一边填满容器
    • 与 aspectRatio 共同实现自顺应布局

四、关键工具方法


  • 默认尺寸盘算
  1. calcImageDefaultSize(imageWHRatio: number, size: window.Size): image.Size {
  2.   if (imageWHRatio > size.width / size.height) {
  3.     return { width: size.width, height: size.width / imageWHRatio };
  4.   } else {
  5.     return { height: size.height, width: size.height * imageWHRatio };
  6.   }
  7. }
复制代码


  • 逻辑剖析:

    • 当图片比屏幕"更宽"(宽高比更大),按屏幕宽度适配
    • 当图片比屏幕"更高",按屏幕高度适配

  • 示例:屏幕 1080x2400,图片 3000x2000(宽高比 1.5)

    • 屏幕宽高比 ≈ 0.45(竖屏)
    • 1.5 > 0.45 → 按宽度 1080px 体现,高度 = 1080 / 1.5 = 720px


  • 缩放比例盘算
  1. calcFitScaleRatio(imageSize: image.Size, windowSize: window.Size): number {
  2.   return Math.max(windowSize.width / imageSize.width,
  3.                  windowSize.height / imageSize.height);
  4. }
复制代码


  • 功能:盘算图片填满屏幕所需的最小缩放比例
  • 使用场景:双击放大时,确保图片能完整添补屏幕
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表