鸿蒙grid-hybrid项目UI滚动联动

grid-hybrid项目 gitee.com/harmonyos_s...

此项目交互场景相对复杂,可作为实际应用交互场景的草稿,进一步完善。譬如百度文库的UI交互。

一、GridNestListIndex页面交互

-- 多种控件的Scroller滚动联动

项目中GridNestListIndex 页面通过以下方式实现了滚动联动效果:


1. 核心组件与状态

  • Scroll 组件:用于页面的整体滚动。
  • List 组件:用于展示网格项列表。
  • Scroller 对象
    • scrollerForScroll:控制页面整体滚动。
    • scrollerForList:控制列表滚动。
    • scrollerForTitle:控制标题栏的横向滚动。
  • 状态变量
    • listPosition:记录列表的滚动位置(顶部、中间、底部)。
    • scrollPosition:记录页面的滚动位置(顶部、中间、底部)。
    • currentIndex:记录当前显示的列表项的索引。

2. 滚动联动实现逻辑

(1) 列表滚动触发标题栏联动

  • onScrollIndex 事件
    • 当列表滚动时,通过 onScrollIndex 获取当前显示的第一个子组件的索引 start
    • 更新 currentIndex 状态,并调用 scrollerForTitle.scrollToIndex 同步标题栏的滚动位置。

(2) 标题栏点击触发列表联动

  • 标题栏点击事件
    • 点击标题栏时,调用 scrollerForList.scrollToIndex 滚动列表到对应索引。
    • 同时调用 scrollerForScroll.scrollEdge(Edge.Bottom) 确保页面滚动到底部(避免标题栏遮挡列表)。
    • 更新 currentIndex 状态。

(3) 页面滚动与列表滚动联动

  • onScrollFrameBegin 事件
    • 当列表滚动时,通过 onScrollFrameBegin 计算偏移量 offset
    • 如果页面已滚动到底部(scrollPosition === ScrollPosition.end),且列表不在顶部或向上滚动,则允许列表继续滚动。
    • 否则,通过 scrollerForScroll.scrollBy 同步页面的滚动。

(4) 页面滚动状态同步

  • onWillScrollonScrollEdge 事件
    • 监听页面滚动方向,更新 scrollPosition 状态(顶部、中间、底部)。
    • 当页面滚动到顶部或底部时,禁止进一步滚动(通过 onScrollFrameBegin 返回 offsetRemain: 0)。

3. 关键代码片段

  • 列表滚动索引同步

    typescript 复制代码
    .onScrollIndex((start: number) => {
      this.currentIndex = start;
      this.scrollerForTitle.scrollToIndex(this.currentIndex);
    })
  • 标题栏点击联动

    typescript 复制代码
    .onClick(() => {
      this.scrollerForList.scrollToIndex(index);
      this.scrollerForScroll.scrollEdge(Edge.Bottom);
      this.scrollerForTitle.scrollToIndex(index);
      this.currentIndex = index;
    })
  • 页面与列表滚动同步

    typescript 复制代码
    .onScrollFrameBegin((offset: number) => {
      if (this.scrollPosition === ScrollPosition.end && (this.listPosition != ScrollPosition.start || offset > 0)) {
        return { offsetRemain: offset };
      } else {
        this.scrollerForScroll.scrollBy(0, offset);
        return { offsetRemain: offset };
      }
    })

4. 总结

通过 Scroller 对象和状态变量的协同工作,GridNestListIndex 实现了以下联动效果:

  1. 列表滚动时,标题栏自动同步到对应位置。
  2. 点击标题栏时,列表滚动到对应项,并确保页面布局正确。
  3. 页面滚动时,动态调整列表的滚动行为,避免冲突。

这种设计确保了用户体验的流畅性和一致性。

-- Grid的样式设置

GridComponent.ets 文件中,Grid 组件的行列数、宽高和布局是通过以下方式控制的:


1. 行列数控制

(1) 列数控制

  • columnsTemplate 属性
    • 通过 CommonConstants.GRID_COLUMNS_TEMPLATE 定义列模板。
    • 例如:'1fr 1fr 1fr 1fr' 表示 4 列,每列宽度均分剩余空间。

(2) 行数动态计算

  • 动态计算
    • 行数由 gridData.gridItemList.length 和列数决定。
    • 例如:Math.ceil(this.gridData.gridItemList.length / 4) 表示每行 4 个项,计算总行数。

2. 宽高控制

(1) 宽度

  • width 属性
    • 默认继承父容器宽度(CommonConstants.FULL_PERCENT)。

    • 可通过 margin 调整左右边距:

      typescript 复制代码
      .margin({
        left: $r('app.float.grid_left_margin'),
        right: $r('app.float.grid_right_margin')
      })

(2) 高度

  • height 属性
    • 通过 getGridHeight() 方法动态计算:

      typescript 复制代码
      .height(this.getGridHeight())
    • 计算逻辑

      • 每行高度固定为 68(网格项高度)。

      • 行间距为 8

      • 上下边距为 12 * 2

      • 公式:

        typescript 复制代码
        gridHeight += Math.ceil(this.gridData.gridItemList.length / 4) * 68; // 行高
        gridHeight += (Math.ceil(this.gridData.gridItemList.length / 4) - 1) * 8; // 行间距
        gridHeight += 12 * 2; // 上下边距

3. 间距与对齐

(1) 行间距

  • rowsGap 属性
    • 通过 $r('app.float.grid_rows_gap_size') 设置行间距。

(2) 内边距

  • padding 属性
    • 通过 $r('app.float.grid_padding_size') 设置内边距。

(3) 圆角

  • borderRadius 属性
    • 通过 $r('app.float.grid_border_radius') 设置圆角。

4. 关键代码片段

typescript 复制代码
Grid() {
  ForEach(this.gridData.gridItemList, (item: string) => {
    GridItemComponent({ itemName: item })
  })
}
.columnsTemplate(CommonConstants.GRID_COLUMNS_TEMPLATE) // 列模板
.margin({ left: $r('app.float.grid_left_margin'), right: $r('app.float.grid_right_margin') }) // 左右边距
.height(this.getGridHeight()) // 动态高度
.rowsGap($r('app.float.grid_rows_gap_size')) // 行间距
.padding($r('app.float.grid_padding_size')) // 内边距
.borderRadius($r('app.float.grid_border_radius')) // 圆角

5. 总结

  • 列数 :由 columnsTemplate 定义(如 4 列)。
  • 行数:动态计算(根据数据项数和列数)。
  • 宽度 :继承父容器,通过 margin 调整边距。
  • 高度:动态计算(行高 + 行间距 + 边距)。
  • 间距与样式 :通过 rowsGappadding 等属性控制。

这种设计确保了网格布局的灵活性和响应性。

二、GridNestSwiperIndex页面交互

GridNestSwiperIndex.ets 文件中,页面通过 SwiperWaterFlow 组件的协同工作,实现了一个动态的混合布局效果。以下是页面的完整解析:


1. 页面结构与功能

(1) 整体布局

  • 顶层容器Column 纵向排列,包含 Swiper(顶部滑动菜单)和 WaterFlow(下方瀑布流内容)。
  • 交互逻辑
    • Swiper 切换分类时,动态调整自身高度,间接影响 WaterFlow 的展示空间。
    • WaterFlow 根据数据源和分区配置,动态渲染内容项。

(2) 核心组件

组件 作用 数据依赖 动态控制点
Swiper 横向滑动菜单 GRID_COL_LIST swiperDistance(高度)
WaterFlow 瀑布流内容展示 WATER_FLOW_DATA sections(分区配置)

2. 数据驱动设计

(1) Swiper 分页与高度

  • 分页数据
    GRID_COL_LIST 定义分页内容和数量,例如:

    typescript 复制代码
    GRID_COL_LIST = [
      ["推荐", "热门"], // 第一页
      ["最新", "分类"]  // 第二页
    ]
  • 高度控制
    通过滑动事件 (onGestureSwipe) 和动画回调 (onAnimationStart) 动态设置 swiperDistance

    typescript 复制代码
    .onGestureSwipe((index: number) => {
      this.swiperDistance = (index === 0) ? SWIPER_HEIGHT_SIZE2 : SWIPER_HEIGHT_SIZE1;
    })

(2) WaterFlow 分区与内容

  • 数据源
    WATER_FLOW_DATA 提供内容项数据(如图片资源),通过 WaterFlowDataSource 封装。

  • 分区配置
    sections 定义布局规则,例如:

    typescript 复制代码
    sections = [
      { itemsCount: 1, crossCount: 1 }, // 单栏Banner
      { itemsCount: 6, crossCount: 2 }  // 双栏商品列表
    ]
  • 动态渲染
    使用 LazyForEach 按需生成 FlowItem

    typescript 复制代码
    LazyForEach(this.waterFlowDataSource, (item: Resource) => {
      FlowItem() {
        Image(item) // 绑定数据
      }
    })

3. 关键交互流程

  1. 初始化

    • 加载 GRID_COL_LISTWATER_FLOW_DATA
    • 配置 sections 分区。
  2. 用户滑动 Swiper

    • 触发 onGestureSwipe → 更新 swiperDistance
    • 动画过渡高度变化。
  3. WaterFlow 响应

    • 高度变化后,layoutWeight(1) 自动调整内容区域空间。
    • 根据当前分区重新布局项。

4. 设计优势与扩展性

(1) 优势

  • 性能优化LazyForEach 懒加载 + 动画平滑过渡。
  • 灵活配置 :通过修改 sections 或数据源即可调整布局。

(2) 扩展建议

  • 动态数据 :通过接口异步更新 GRID_COL_LISTWATER_FLOW_DATA
  • 高度自适应 :根据 WaterFlow 内容高度动态计算 swiperDistance

如果需要进一步调整或扩展功能,请具体说明需求!

相关推荐
小周同学:13 小时前
【UniApp打包鸿蒙APP全流程】如何配置并添加UniApp API所需的鸿蒙系统权限
华为·uni-app·harmonyos
iFlyCai14 小时前
鸿蒙开发中的List组件详解
华为·list·harmonyos
前端世界19 小时前
HarmonyOS 实战:6 种实现实时数据更新的方案全解析(含完整 Demo)
华为·harmonyos
万少1 天前
可可图片编辑 HarmonyOS 上架应用分享
前端·harmonyos
zhanshuo1 天前
鸿蒙开发实战:掌握 Promise 和 async/await,轻松搞定异步请求
harmonyos
simple_lau1 天前
H5资源包热更新:从下载、解压到渲染的实现方案
typescript·harmonyos·arkts
程序员二师兄2 天前
记一次鸿蒙webview图片渲染失败的问题
前端·javascript·harmonyos
缘澄2 天前
ArkTs声明式UI开发
harmonyos
大雷神2 天前
鸿蒙中应用框架和应用模型
华为·harmonyos