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

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

作者头像
全栈若城
发布于 2025-03-16 12:42:42
发布于 2025-03-16 12:42:42
4700
代码可运行
举报
文章被收录于专栏:若城技术专栏若城技术专栏
运行总次数:0
代码可运行

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

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

一、组件整体架构
1. 组件功能
  • 实现图片预览功能,支持水平和垂直滑动
  • 支持懒加载和手势交互
  • 可自定义背景色和切换动画
  • 适配不同屏幕尺寸
2. 技术栈
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
HarmonyOS ETS + 自定义手势 + 矩阵变换 + 懒加载

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

三、关键方法详解
1. 数据初始化
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
aboutToAppear(): void {
    this.getListMaxLength()
}

getListMaxLength() {
    this.listMaxLength = this.imageList.length
    this.lazyImageList.clearAndPushAll(this.imageList)
}
  • 生命周期:组件创建时触发
  • 数据转换:将普通数组转为懒加载数据源
2. 滚动控制逻辑
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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. 页面跳转
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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. 列表构建
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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. 列表配置
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
.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. 透明边框处理
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
.borderWidth(1)
.borderColor(Color.Transparent)
  • 问题背景:修复鸿蒙系统Y轴定位异常
  • 解决方案:添加透明边框占位
  • 注意事项:不可移除,等待系统修复
2. 背景色切换
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
.onClick(() => {
    this.listBGColor = this.listBGColor === Color.White 
        ? Color.Black 
        : Color.White
})
  • 交互功能:点击列表切换背景色
  • 实现原理:通过@State触发重新渲染

六、组件使用示例
1. 父组件调用
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@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. 手势优化
    • 自定义手势控制替代系统滚动
    • 精准的动画时长控制
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-03-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

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

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Appium常用操作之「Toast提示信息获取」
安卓 4.4 以上的版本都是基于 UiAutomator,现在已经改为 UiAutomator2 了。所以 Toast 在原来的 UiAutomator 基础上没办法识别,没法识别的话就需要利用 UiAutomator2了。
清菡
2020/11/20
2.5K3
Appium+python自动化29-toast消息
前言 appium1.5以后的版本才支持toast定位,并且 'automationName'得设置为'Uiautomator2',才能捕获到。 一、 Supported Platforms 1.查看appium v1.7版本[官方文档](https://github.com/appium/appium/) **Supported Platforms** Appium supports app automation across a variety of platforms, like iOS, Andro
上海-悠悠
2018/04/08
1.6K0
Appium+python自动化29-toast消息
史上最全 Appium 自动化测试从入门到框架实战精华学习笔记(三)
本系列文章汇总了从 Appium 自动化测试从基础到框架高级实战中,所涉及到的方方面面的知识点精华内容(如下所示),希望对大家快速总结和复习有所帮助。
霍格沃兹测试开发
2022/05/30
1.2K0
Appium自动化测试框架综合实践
注册一个新的账号(账户和密码可以随机生成),完善院校和专业信息 (如:院校:上海-同济大学 专业:经济学类-统计学-经济统计学)
清风穆云
2021/08/09
7330
工厂设计模式在自动化中的引用(二)
工厂设计模式在自动化中的引用(一)中介绍了利用工厂设计模式,整合selenium2和appium,写在一个框架中,可以实现对web应用程序,移动应用程序的自动化测试,在之前介绍了对web的测试实例代码,本文章介绍对移动应用程序的测试,关于appium本文章先不介绍,待后期完整的介绍appium的知识体系。在一个测试工厂中,生产一个可以测试web,可以测试app的测试工具,测试web或app什么,给什么框架测试,相互独立而有相互有依据,互相不影响,见如下的流程图:
无涯WuYa
2018/10/25
8830
工厂设计模式在自动化中的引用(二)
Appium+python自动化(三十九)-Appium自动化测试框架综合实践 - 代码实现(超详解)
 前边一直在分享testng的相关文章,看了点赞量和阅读数不是很高,宏哥猜测估计是大家确实是用不到或者不喜欢吧!不过宏哥经过一段时间的准备,appium的自动化测试框架完善的差不多了,那么接下来宏哥继续给小伙伴和童鞋们分享有关Appium自动化测试框架综合实践。想必小伙伴们有点等不及了吧!
北京-宏哥
2019/11/14
1.9K0
Appium+python自动化(二十四)- 白素贞千年等一回许仙 - 元素等待(超详解)
  许仙小时候最喜欢吃又甜又软的汤圆了,一次一颗汤圆落入西湖,被一条小白蛇衔走了。十几年后,一位身着白衣、有青衣丫鬟相伴的美丽女子与许仙相识了,她叫白娘子。白娘子聪明又善良,两个人很快走到了一起。靠着自己的力量,他们过上了幸福的生活。一天,僧人法海找到许仙,警告说白娘子是一条修行千年的蛇精,许仙不信。到了端午节,勉强喝下了雄黄酒的白娘子现了原形,许仙被吓得昏死过去。原来白娘子真的是之前吃下许仙汤圆的小蛇。白娘子辛苦救回了许仙的性命,但之后法海却以保护许仙的名义将他囚禁起来,白娘子与小青召集虾兵蟹将,要逼法海放出许仙。突然一座宝塔从天而降,把白娘子镇在了塔下…… 想必小伙伴和童鞋们都听过,或者是看过这个故事,是多么的痴情感人,尤其是千年等一回的歌曲是一个经典音乐。好了废话还是少说,进入今天的主题--元素等待   前边介绍了APP页面元素的识别定位、操作等技术,可能你会觉得掌握这两项技术就可以实施APP自动化了,答案基本是这样的,毕竟元素定位和操作是核心技术。但是,在某些场景,脚本的运行并非预期那样,如,要操作的元素用常规方法无法识别、元素可以识别但在脚本运行时却未如期而至等。为了解决这些疑难杂症,接下来内容将会介绍处理这些问题的通用方法。   在本节,主要介绍元素等待的使用方法和场景,该方法是开发稳定、高容错性自动化脚本的前提。
北京-宏哥
2019/07/30
1.3K0
Appium+python自动化(二十四)- 白素贞千年等一回许仙 - 元素等待(超详解)
Appium+python自动化(二十六)- 烟花一瞬,昙花一现 -Toast提示(超详解)
  今天宏哥在这里首先给小伙伴们和童鞋们分享一个有关昙花的小典故:话说昙花原是一位花神,她每天都开花,四季都灿烂。她还爱上了每天给她浇水除草的年轻人。后来,此事给玉帝得知。于是,玉帝大发雷霆,要拆散鸳鸯。他将花神抓了起来,把她贬为每年只能开一瞬间的昙花,不让她再和情郎相见,还把那年轻人送去灵鹫山出家,赐名韦陀,让他忘记前尘,忘记花神。   多年过去了,韦陀果真忘了花神,潜心习佛,渐有所成。而花神却怎么也忘不了那个曾经照顾她的小伙子。她知道每年暮春时分,韦陀总要下山来为佛祖采集朝露煎茶。所以,昙花就选择在那个时候开放。她把集聚了整整一年的精气绽放在那一瞬间,希望韦陀能回头看她一眼,能记起她。可是,千百年间过去了,韦陀一年年的下山来采集朝露,昙花一年年的默默绽放,韦陀始终没有记起她。直到有一天,一名枯瘦的男子从昙花身边走过,看到花神忧郁孤苦之情,便停下脚步问花神:“你为什么哀伤?”。花神惊异,因为凡人是看不到花神的真身。如果是大罗金仙头上有金光、如果是妖魔头上有黑气、如果而凡人头上是无任何灵光。刚刚从身边走过的明明是一个凡人,如何看得见自己的真身。花神犹豫片刻,只是答到:“你帮不了我”。又默默等待韦陀,不再回答那个男子的话。40年后,那个枯瘦男子又从昙花身边走过,重复问了40年前的那句话:“你为什么哀伤?”花神再次犹豫片刻,只是答道“你也许帮不了我”。枯瘦的男子笑了笑离开。再40年后,一个枯瘦的老人再次出现在花神那里,原本枯瘦的老人看起来更是奄奄一息。当年的男子已经变成老人,但是他依旧问了和80年前一样的话:“你为什么哀伤?”。昙花答道:“谢谢你这个凡人,在你一生问过我3次,但是你毕竟是凡人,而且已经奄奄一息,还怎么帮我,我是因爱而被天罚的花神”。老人笑了笑,说“我是聿明氏,我只是来了断80年前没有结果的那段缘分。花神,我只送你一句‘缘起缘灭缘终尽、花开花落花归尘’”。说完老人闭目坐下。时间渐渐过去,夕阳的最后一缕光线开始从老人的头发向眼睛划去。老人笑道:“昙花一现为韦陀,这般情缘何有错,天罚地诛我来受,苍天无眼我来开”。说罢,老人一把抓住花神。此时的夕阳正好滑到了老人的眼睛,老人随即圆寂,抓着花神一同去往佛国去。花神在佛国见到了韦陀,韦陀也终于想起来前世因缘。佛祖知道后准韦陀下凡了断未了的因缘。   昙花一现,只为韦陀。所以,昙花又名韦陀花。也因为昙花是在夕阳后见到韦陀,所以昙花都是夜间开放。   好了,到此故事结束了,开始今天的主题 - 获取toast提示 在日常使用App过程中,经常会看到App界面有一些弹窗提示(如下图所示)这些提示元素出现后等待3秒左右就会自动消失,这个和我日常生活中看到的烟花和昙花是多么的相似,那么我们该如何获取这些元素文字内容呢?
北京-宏哥
2019/08/05
1.8K0
Appium+python自动化(二十六)- 烟花一瞬,昙花一现 -Toast提示(超详解)
[云+社区年度征文]Appium上下文和H5测试(二)
进入这个页面也是需要时间的。WebView 这个元素当中,放的才是 html 页面。真的等到 html 页面加载出来之后,再去获取所有相关的内容,这样比较好。
清菡
2020/11/30
5300
如何在iphone真机上自动化测试
我们做自动化测试的时候,有的时候需要用模拟器来跑。 主要好处是:节约设备,不需要占用实际的设备资源;而且不会锁屏,需要充电等各种烦恼。 有的时候却用真机跑有好处,他们的区别是什么? 1.模拟器太慢
赵云龙龙
2020/05/22
2.1K0
[云+社区年度征文]Appium常用操作之「元素定位、swipe 滑屏操作」
建议不用 layui。layui 在有些情况下定位元素是有问题的。在环境基本上是正确的情况下,它截图截不到。所以可以舍弃 layui,直接用自带的 uiautomatorviewer(现在拥有的定位方式,它全部都支持)。
清菡
2020/10/30
2K0
appium+python手机app自动化测试配置和测试代码示例
pip install selenium -i https://pypi.tuna.tsinghua.edu.cn/simple/
coffee1
2024/03/16
3900
appium中ios元素定位
appium中,IOS和Android元素定位方法有些不同。 查找元素的顺序,个人认为速度从快到慢的顺序是这样的: ios_predicate >> accessibility_id >> class_name >>xpath 可以写个demo来测试一下。
赵云龙龙
2021/04/23
3.3K0
Appium常用操作之「微信滑屏、触屏操作」
不需要看到欢迎页面,直接做里面的后续操作就好了。也就是我想记住一些用户的习惯, 不要像第一次访问一样,有一个重置与否,给它关闭了。
清菡
2020/11/04
1.7K0
基于Selenium Grid 分布式管理的appium测试设备系统(二)
在之前快速搭建基于Selenium Grid 分布式管理的appium测试设备系统,我们介绍了快速本地化搭建,本次我们分享的呢,是基于搭建后的,如何在代码上进行调度设备测试?
雷子
2021/12/16
6990
基于Selenium Grid 分布式管理的appium测试设备系统(二)
Appium上下文和H5测试(一)
微信小程序的前提都是基于 H5,没有 H5 的情况下来操作微信小程序您可能不太明白。H5 是混合应用,有原生应用和混合应用。
清菡
2020/11/25
7020
Appium自动化测试 —— 断言
😏作者简介:博主是一位测试管理者,同时也是一名对外企业兼职讲师。 📡主页地址:【Austin_zhai】 🙆目的与景愿:旨在于能帮助更多的测试行业人员提升软硬技能,分享行业相关最新信息。 💎声明:博主日常工作较为繁忙,文章会不定期更新,各类行业或职场问题欢迎大家私信,有空必回。
Austin_zhai
2023/10/18
5880
Appium自动化测试 —— 断言
Appium系列(三十七)在测试用例增加等待
在测试用例执行的时候,我们可能出现元素时而能点击,时而无法点击,这可能就是因为没有加载出来,我们就执行了。那么我们应该怎么做呢,
雷子
2021/07/06
4650
Appium系列(三十七)在测试用例增加等待
appium+python自动化测试教程_python+appium自动化
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
全栈程序员站长
2022/10/04
3870
自动化测试之Page Object
web自动化的测试最大的挑战之一也许就是随着项目的进展,项目在不停的变化,测试这边也得跟着项目变化来保障项目的顺利进展,在现实的软件项目中,变化是一个常数,而我们只有适应变化,才可以把握变化,但是自动化这边必须要考虑的一个现实问题就是,如何可以更加高效的提高代码的维护量,如何更加完美的来重构编写的代码?另外需要考虑的是,在一个现实的项目中,不管需求是多么的变化,编写的自动化的case以及这些case的代码量多么多,在一个敏捷的项目中,需要在一个版本提交测试后,测试这边务必在有限的时间内给出测试报告,这期间,就包含了自动化的执行,自动化的测试报告以及自动化执行后,对错误的分析(可能是代码错误?可能是功能错误?),和某些需求变化后,对自动化代码的重构,很显然,使用以前的方式很难解决这样的一个现实问题。
无涯WuYa
2018/10/25
8290
自动化测试之Page Object
推荐阅读
相关推荐
Appium常用操作之「Toast提示信息获取」
更多 >
LV.1
这个人很懒,什么都没有留下~
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验