ArkUI WaterFlow:瀑布流不是把卡片随便往下塞

举报
蓝瘦的蜕变 发表于 2026/08/10 14:19:10 2026/08/10
【摘要】 瀑布流适合“等宽但高度不一样”的内容。它不是把卡片随便往下塞,而是让每个子项根据列的高度自然补位。 Demo 里只做静态瀑布流 这篇先不讲无限加载、LazyForEach、WaterFlowSections。我们只看最基础的结构:WaterFlow 容器和 FlowItem 子项。 columnsTemplate('1

ArkUI WaterFlow:瀑布流不是把卡片随便往下塞

瀑布流适合“等宽但高度不一样”的内容。它不是把卡片随便往下塞,而是让每个子项根据列的高度自然补位。

Demo 里只做静态瀑布流

这篇先不讲无限加载、LazyForEachWaterFlowSections。我们只看最基础的结构:WaterFlow 容器和 FlowItem 子项。

WaterFlow() {
  ForEach(this.items, (item: WaterFlowDemoItem) => {
    FlowItem() {
      this.flowCard(item)
    }
  }, (item: WaterFlowDemoItem) => item.title)
}
.columnsTemplate('1fr 1fr')
.columnsGap(10)
.rowsGap(10)

columnsTemplate('1fr 1fr') 表示两列等宽。columnsGap 控制列间距,rowsGap 控制行间距。瀑布流的气质很大程度上就靠这两个间距撑住。

不要急着做无限滚动

很多瀑布流最后都会走向无限加载,但入门时不建议一上来就做。因为新增数据、懒加载通知、布局重算这些细节会把主题带跑。先把静态错落布局看明白,后面再拆性能和懒加载。

你更常见的瀑布流场景是什么?图片墙、商品卡、还是资讯推荐?不同内容高度差不一样,间距也要跟着调。

参考文档: https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-list-and-grid

完整示例代码

文件位置:entry/src/main/ets/pages/arkUI/listLayout/ArkUIWaterFlowDemo.ets

class WaterFlowDemoItem {
  title: string = '';
  desc: string = '';
  height: number = 100;
  color: string = '';

  constructor(title: string, desc: string, height: number, color: string) {
    this.title = title;
    this.desc = desc;
    this.height = height;
    this.color = color;
  }
}

@Entry
@Component
struct ArkUIWaterFlowDemo {
  private items: WaterFlowDemoItem[] = [
    new WaterFlowDemoItem('灵感卡片', '短内容', 112, '#2563EB'),
    new WaterFlowDemoItem('图片备注', '高度更高一点', 152, '#0F766E'),
    new WaterFlowDemoItem('商品推荐', '同宽不同高', 132, '#C2410C'),
    new WaterFlowDemoItem('旅行清单', '错落排列', 176, '#7C3AED'),
    new WaterFlowDemoItem('阅读摘录', '不要硬拉齐', 124, '#1D4ED8'),
    new WaterFlowDemoItem('今日收藏', '自然补位', 158, '#334155')
  ];

  @Builder
  sectionTitle(title: string, desc: string) {
    Column({ space: 4 }) {
      Text(title)
        .width('100%')
        .fontSize(16)
        .fontWeight(700)
        .fontColor('#0F172A')

      Text(desc)
        .width('100%')
        .fontSize(13)
        .fontColor('#64748B')
        .lineHeight(20)
    }
    .width('100%')
    .alignItems(HorizontalAlign.Start)
  }

  @Builder
  flowCard(item: WaterFlowDemoItem) {
    Column({ space: 8 }) {
      Text(item.title)
        .width('100%')
        .fontSize(16)
        .fontWeight(700)
        .fontColor('#FFFFFF')

      Text(item.desc)
        .width('100%')
        .fontSize(12)
        .fontColor('#E2E8F0')
        .lineHeight(18)
    }
    .width('100%')
    .height(item.height)
    .padding({ left: 14, right: 14, top: 14, bottom: 14 })
    .justifyContent(FlexAlign.End)
    .alignItems(HorizontalAlign.Start)
    .backgroundColor(item.color)
    .borderRadius(8)
  }

  build() {
    Scroll() {
      Column({ space: 18 }) {
        Text('ArkUI WaterFlow')
          .width('100%')
          .fontSize(24)
          .fontWeight(700)
          .fontColor('#0F172A')

        Text('瀑布流不是把卡片随便往下塞')
          .width('100%')
          .fontSize(22)
          .fontWeight(700)
          .fontColor('#111827')

        Text('这一页只看静态瀑布流。WaterFlow 适合等宽但高度不一样的内容,列间距和行间距要先设置清楚。')
          .width('100%')
          .fontSize(14)
          .fontColor('#64748B')
          .lineHeight(22)

        Column({ space: 12 }) {
          this.sectionTitle('两列瀑布流先看错落感', 'columnsTemplate 决定列数,FlowItem 是每个瀑布流子项。高度不同的卡片会自然补到更短的列里。')

          WaterFlow() {
            ForEach(this.items, (item: WaterFlowDemoItem) => {
              FlowItem() {
                this.flowCard(item)
              }
            }, (item: WaterFlowDemoItem) => item.title)
          }
          .width('100%')
          .height(420)
          .columnsTemplate('1fr 1fr')
          .columnsGap(10)
          .rowsGap(10)
        }
        .width('100%')
        .padding(16)
        .backgroundColor('#EFF6FF')
        .borderRadius(8)

        Column({ space: 12 }) {
          this.sectionTitle('间距决定它像不像信息流', '瀑布流最怕卡片贴得太近。columnsGap 和 rowsGap 是第一批要调的参数。')

          WaterFlow() {
            ForEach(this.items.slice(0, 4), (item: WaterFlowDemoItem) => {
              FlowItem() {
                this.flowCard(item)
              }
            }, (item: WaterFlowDemoItem) => item.title)
          }
          .width('100%')
          .height(300)
          .columnsTemplate('1fr 1fr')
          .columnsGap(16)
          .rowsGap(16)
        }
        .width('100%')
        .padding(16)
        .backgroundColor('#F8FAFC')
        .borderRadius(8)
      }
      .width('100%')
      .padding(20)
      .alignItems(HorizontalAlign.Start)
    }
    .width('100%')
    .height('100%')
    .backgroundColor('#FFFFFF')
  }
}
【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请自行联系原作者进行授权。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。