前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >70.HarmonyOS NEXT PicturePreview组件深度剖析:从架构设计到核心代码实现

70.HarmonyOS NEXT PicturePreview组件深度剖析:从架构设计到核心代码实现

原创
作者头像
全栈若城
发布2025-03-15 21:48:36
发布2025-03-15 21:48:36
620
举报

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

HarmonyOS NEXT PicturePreview组件深度剖析:从架构设计到核心代码实现

一、组件整体架构

1. 组件功能
  • 实现图片预览功能,支持水平和垂直滑动
  • 支持懒加载和手势交互
  • 可自定义背景色和切换动画
  • 适配不同屏幕尺寸
2. 技术栈

HarmonyOS ts + 自定义手势 + 矩阵变换 + 懒加载


二、核心代码解析

1. 组件参数
代码语言:ts
复制
@Prop listDirection: Axis = Axis.Vertical // 滑动方向(默认垂直)
@Link @Watch('getListMaxLength') imageList: string[] // 双向绑定的图片数据源
  • @Prop:父组件传入的不可变参数
  • @Link:实现父子组件双向数据绑定
  • @Watch:当imageList变化时自动触发getListMaxLength
2. 状态管理
代码语言:ts
复制
@State listBGColor: Color = Color.White // 背景色状态
@State lazyImageList: CommonLazyDataSourceModel<string> // 懒加载数据源
  • @State:组件内部状态,变化触发UI更新
  • CommonLazyDataSourceModel:优化内存的懒加载模型
3. 控制相关
代码语言:ts
复制
private listScroll: ListScroller = new ListScroller() // 列表滚动控制器
private listAnimationDuration: number = 500 // 滑动动画时长
  • ListScroller:精确控制列表滚动位置
  • 动画时长控制滑动流畅度

三、关键方法详解

1. 数据初始化
代码语言:ts
复制
aboutToAppear(): void {
    this.getListMaxLength()
}

getListMaxLength() {
    this.listMaxLength = this.imageList.length
    this.lazyImageList.clearAndPushAll(this.imageList)
}
  • 生命周期:组件创建时触发
  • 数据转换:将普通数组转为懒加载数据源
2. 滚动控制逻辑
代码语言:ts
复制
setListOffset(offset: number, animationDuration: number = 0) {
    const WIN_SIZE = windowSizeManager.get()
    // 计算主轴尺寸
    let principalAxisSize = this.listDirection === Axis.Horizontal 
        ? WIN_SIZE.width 
        : WIN_SIZE.height
    // 计算偏移量
    let principalAxisOffset = principalAxisSize * this.listIndex + this.listSpace * this.listIndex
    // 执行滚动
    this.listScroll.scrollTo({
        yOffset: this.listDirection === Axis.Horizontal ? 0 : principalAxisOffset,
        xOffset: this.listDirection === Axis.Horizontal ? principalAxisOffset : 0,
        animation: { duration: animationDuration }
    })
}
  • 窗口适配:通过windowSizeManager获取屏幕尺寸
  • 方向判断:根据滑动方向计算不同轴向的偏移量
  • 平滑滚动:支持自定义动画时长
3. 页面跳转
代码语言:ts
复制
setListToIndex(index: number) {
    // 边界检查
    let nIndex = Math.max(0, Math.min(index, this.listMaxLength - 1))
    // 计算目标位置
    const principalAxisSize = this.listDirection === Axis.Horizontal 
        ? windowSizeManager.get().width 
        : windowSizeManager.get().height
    const calculatedOffset = nIndex * (principalAxisSize + this.listSpace)
    // 执行跳转
    this.listScroll.scrollTo({
        xOffset: this.listDirection === Axis.Horizontal ? calculatedOffset : 0,
        yOffset: this.listDirection === Axis.Vertical ? calculatedOffset : 0,
        animation: { duration: this.listAnimationDuration }
    })
}
  • 安全处理:限制index在有效范围内
  • 精确计算:考虑列表间距(listSpace)的影响
  • 动画控制:使用预设动画时长保证体验一致

四、UI构建逻辑

1. 列表构建
代码语言:ts
复制
List({ 
    scroller: this.listScroll, 
    space: this.listSpace 
}) {
    LazyForEach(this.lazyImageList, (imageUrl: string, index: number) => {
        ListItem() {
            PicturePreviewImage({
                imageUrl: imageUrl,
                // 传递参数...
            })
        }
        .width("100%")
    })
}
  • LazyForEach:优化性能的懒加载循环
  • ListItem:每个图片项的容器
  • width("100%"):撑满父容器宽度
2. 列表配置
代码语言:ts
复制
.enableScrollInteraction(false) // 禁用默认滑动
.scrollSnapAlign(ScrollSnapAlign.START) // 对齐方式
.cachedCount(1) // 缓存数量
.listDirection(this.listDirection) // 滑动方向
.scrollBar(BarState.Off) // 隐藏滚动条
.expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP, SafeAreaEdge.BOTTOM])
  • 关键配置
    • enableScrollInteraction(false):避免与自定义手势冲突
    • cachedCount(1):平衡内存与性能
    • expandSafeArea:适配系统安全区域

五、特殊处理说明

1. 透明边框处理
代码语言:ts
复制
.borderWidth(1)
.borderColor(Color.Transparent)
  • 问题背景:修复鸿蒙系统Y轴定位异常
  • 解决方案:添加透明边框占位
  • 注意事项:不可移除,等待系统修复
2. 背景色切换
代码语言:ts
复制
.onClick(() => {
    this.listBGColor = this.listBGColor === Color.White 
        ? Color.Black 
        : Color.White
})
  • 交互功能:点击列表切换背景色
  • 实现原理:通过@State触发重新渲染

六、组件使用示例

1. 父组件调用
代码语言:ts
复制
@Entry
@Component
struct Example {
    @State images: string[] = [
        "common/image1.jpg",
        "common/image2.jpg",
        "common/image3.jpg"
    ]

    build() {
        Column() {
            PicturePreview({
                imageList: $rawfile(this.images),
                listDirection: Axis.Horizontal
            })
        }
    }
}
2. 参数说明

参数名

类型

必填

说明

imageList

string[]

图片路径数组

listDirection

Axis

滑动方向(默认垂直)


七、性能优化点

  1. 懒加载机制
    • 使用LazyForEach按需创建列表项
    • cachedCount(1)减少内存占用
  2. 渲染优化
    • 固定尺寸计算避免重复布局
    • 禁用不必要的滚动条
  3. 手势优化
    • 自定义手势控制替代系统滚动
    • 精准的动画时长控制

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • HarmonyOS NEXT PicturePreview组件深度剖析:从架构设计到核心代码实现
    • 一、组件整体架构
    • 二、核心代码解析
    • 三、关键方法详解
    • 四、UI构建逻辑
    • 五、特殊处理说明
    • 六、组件使用示例
    • 七、性能优化点
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档