鸿蒙HarmonyOS 5.0开发实战:滚动吸顶效果实现案例

[复制链接]
发表于 2025-4-13 05:52:08 | 显示全部楼层 |阅读模式
 往期鸿蒙5.0全套实战文章必看:(文中附带鸿蒙5.0全栈学习资料)



  • 鸿蒙开发焦点知识点,看这篇文章就够了
  • 最新版!鸿蒙HarmonyOS Next应用开发实战学习路线
  • 鸿蒙HarmonyOS NEXT开发技术最全学习路线指南
  • 鸿蒙应用开发实战项目,看这一篇文章就够了(部分项目附源码)

先容

本示例先容运用Stack组件以构建多层次堆叠的视觉效果。通过绑定Scroll组件的onScroll滚动事件回调函数,精准捕获滚动动作的发生。当滚动时,实时地调节组件的透明度、高度等属性,从而成功实现了嵌套滚动效果、透明度动态变化以及平滑的组件切换。其中,搜索框能够实现“吸顶”效果,在用户滚动页面时始终保持在顶部。
效果图预览



使用说明

  • 加载完成后显示整个界面,凌驾一屏可以上下滑动可见嵌套滚动效果。
  • 当滚动页面时,搜索框的位置会随着父级Scroll组件的滚动而变化。当父级Scroll组件滚动到底部时,搜索框恰恰位于屏幕顶部。此时,父级Scroll组件制止滚动,子级Scroll组件开始滚动,实现嵌套滚动效果,从而实现搜索框的“吸顶”功能
实现思路


  • 在向上滑动过程中观察到头部组件(头像和二维码布局界面)是处于层级底部,而其他组件覆盖在其上方,为此,选择Stack组件来获取堆叠效果。搜索框的“吸顶”效果,通过监听onDidScroll事件来捕捉父级Scroll组件沿Y轴滚动的间隔,并实时调整搜索框的高度。当用户滚动页面时,搜索框的位置会随着父级Scroll组件的滚动而变化。当父级Scroll组件滚动到底部时,搜索框恰恰位于屏幕顶部,此时通过设置.nestedScroll属性(参考下面第4点)来控制父级与子级Scroll组件之间的嵌套滚动效果,进而实现搜索框的“吸顶”功能
  1. Stack({ alignContent: Alignment.Top }) {
  2.   Flex({ justifyContent: FlexAlign.SpaceBetween }) {
  3.     // 头像和二维码页面布局代码
  4.     // ...
  5.   }
  6.   Scroll(this.scroller) {
  7.     // ...
  8.   }
  9.   .onDidScroll(() => {
  10.     // 获取滑动距离
  11.     const yOffset: number = this.scroller.currentOffset().yOffset;
  12.     // this.searchHeight 随 yOffset变化的公式。按需调整。
  13.     this.searchHeight = this.searchHeightRaw - yOffset * 0.6;
  14.   })
  15. }
复制代码

  • 在搜索栏下方的快捷功能区,向上滑动时,快捷功能区会渐渐隐藏,出现一个横向的新布局的快捷功能区,此处也通过使用Stack组件来获取堆叠效果。
  1. Stack({ alignContent: Alignment.Top }) {
  2.   // 图标背景为白色快捷功能区
  3.   IconView({
  4.     isChange: this.isChange,
  5.     marginSpace: this.marginSpace,
  6.     opacity1: this.opacity1
  7.   })
  8.   // Scroll滚动子组件
  9.   Scroll(this.scroller2) {
  10.     // 向上滑动透明的横向快捷区逐渐显示的布局代码
  11.     // 上图下文字透明背景样式布局代码
  12.     // 商品列表组件布局代码
  13.     // ...
  14.   }
  15. }
复制代码

  • 实现滚动过程中动态调整文本框高度的功能时,运用Scroll组件滚动事件回调函数onDidScroll在滚动时修改文本框的高度及组件的透明度。
  1. .onDidScroll(() => {
  2.   // 通过Scroll的偏移量来动态修改透明度、尺寸和颜色等属性
  3.   // ...
  4. })
复制代码

  • 存在多层嵌套滚动的情况时,应该先滚动父组件,再滚动自身。只必要在内层的Scroll组件的属性nestedScroll设置向前向后两个方向上的嵌套滚动模式,实现与父组件的滚动联动。
  1. Scroll(this.scroller2){
  2.   // ...
  3. }
  4. .width('100%')
  5. .scrollBar(BarState.Off)
  6. .nestedScroll({
  7.   scrollForward: NestedScrollMode.PARENT_FIRST, // 可滚动组件往末尾端滚动时的嵌套滚动选项,父组件先滚动,父组件滚动到边缘以后自身滚动。
  8.   scrollBackward: NestedScrollMode.SELF_FIRST // 可滚动组件往起始端滚动时的嵌套滚动选项,自身先滚动,自身滚动到边缘以后父组件滚动。
  9. })
复制代码

  • 在商品列表区域,接纳瀑布流(WaterFlow)容器进行布局,将商品信息动态分布并分成两列出现,每列商品自上而下排列。
  1. WaterFlow() {
  2.   LazyForEach(this.productData, (item: ProductDataModel) => {
  3.     FlowItem() {
  4.       // ...
  5.   }, (item: ProductDataModel) => item.id.toString())
  6. }
  7. .nestedScroll({
  8.   scrollForward: NestedScrollMode.PARENT_FIRST,
  9.   scrollBackward: NestedScrollMode.SELF_FIRST
  10. })
  11. .columnsTemplate("1fr 1fr")
  12. }
复制代码

  • 在商品列表(ProductList.ets)中,由于进入页面时只显示前两条数据,所以使用分帧加载的方式,在第一帧中将前两条数据放入到列表中,在第二帧中放入剩余数据。
  1. aboutToAppear() {
  2.     // 创建DisplaySync对象
  3.     this.displaySync = displaySync.create();
  4.     // 设置期望帧率
  5.     const range: ExpectedFrameRateRange = {
  6.       expected: 120,
  7.       min: 60,
  8.       max: 120
  9.     };
  10.     this.displaySync.setExpectedFrameRateRange(range);
  11.     // 添加帧回调
  12.     this.displaySync.on("frame", () => {
  13.       // 第一帧中加载前两条数据
  14.       if (this.frame === 1) {
  15.         this.productData.pushData(PRODUCT_DATA.slice(0, 2))
  16.         this.frame += 1;
  17.       } else if (this.frame === 2) {
  18.         // 第二帧中放入剩余数据
  19.         this.productData.pushData(PRODUCT_DATA.slice(2, PRODUCT_DATA.length));
  20.         this.frame += 1;
  21.         this.displaySync?.stop();
  22.       }
  23.     });
  24.     // 开启帧回调监听
  25.     this.displaySync.start();
  26.   }
复制代码
性能知识点

本示例使用了LazyForEach进行数据懒加载,WaterFlow布局时会根据可视区域按需创建FlowItem组件,并在FlowItem滑出可视区域外时销毁以降低内存占用。 本例中Scroll组件绑定onScroll滚动事件回调,onScroll属于频繁回调,在回调中必要尽量淘汰耗时和冗余操作,比方淘汰不须要的日记打印。 本例中使用DisplaySync分帧加载数据,淘汰动画首帧响应时间,降低加载数据的完成时延。
工程布局&模块类型

  1. componentstack                                   // har类型
  2. |---mock
  3. |   |---IconMock.ets                             // 本地数据源
  4. |---model
  5. |   |---DataSource.ets                           // 列表数据模型
  6. |   |---IconModel.ets                            // 数据类型定义
  7. |---view
  8. |   |---ComponentStack.ets                       // 滚动吸顶效果实现案例主页面
  9. |   |---IconView.ets                             // 按钮快捷入口自定义组件
  10. |   |---ProductList.ets                          // 商品列表自定义组件
复制代码



免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

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

×
回复

使用道具 举报

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