ArkUI LazyVGridLayout:数据一多,就别一次性全摆上来

举报
蓝瘦的蜕变 发表于 2026/08/12 09:32:54 2026/08/12
【摘要】 今天我们把网格列表再往前推一步:当入口变多时,用 LazyVGridLayout 搭一个固定高度、能滚动的多列区域。 这篇不讲无限加载,也不讲数据源增删。我们先把最基础的事情做稳:列怎么分、行列间距怎么写、卡片怎么放进去。 先准备一组卡片数据 页面里用 LazyGridCard 放标题、说明和颜色。这样写纯粹为了让 D

ArkUI LazyVGridLayout:数据一多,就别一次性全摆上来

今天我们把网格列表再往前推一步:当入口变多时,用 LazyVGridLayout 搭一个固定高度、能滚动的多列区域。

这篇不讲无限加载,也不讲数据源增删。我们先把最基础的事情做稳:列怎么分、行列间距怎么写、卡片怎么放进去。

先准备一组卡片数据

页面里用 LazyGridCard 放标题、说明和颜色。这样写纯粹为了让 Demo 看起来像一个真实入口区,重点仍然是布局。

private cards: LazyGridCard[] = [
  new LazyGridCard('消息', '统一收口', '#2563EB'),
  new LazyGridCard('日程', '今天先看', '#0F766E')
];

如果你只是验证布局,数组写死就够了。别一上来就把接口、分页、缓存都塞进来,那些应该放到后面的数据章节。

两列等宽先用 columnsTemplate

核心代码是这一段:

LazyVGridLayout() {
  ForEach(this.cards, (item: LazyGridCard, index: number) => {
    this.cardItem(item, index)
  }, (item: LazyGridCard) => item.title)
}
.columnsTemplate('1fr 1fr')
.rowsGap(LengthMetrics.vp(10))
.columnsGap(LengthMetrics.vp(10))

columnsTemplate('1fr 1fr') 表示两列等宽。rowsGap 管上下间距,columnsGap 管左右间距。当前 SDK 里这两个方法接收 LengthMetrics,所以这里用 LengthMetrics.vp(),不要直接写数字。

固定高度滚动区

外层用 WaterFlow 承载这块固定高度区域,LazyVGridLayout 负责里面的列模板:

WaterFlow() {
  LazyVGridLayout() {
    // card items
  }
}
.height(330)

这样入口数量变多时,页面不会被撑得没边,用户也能在这块区域里自然滚动。

你可以自己把 columnsTemplate 改成 '1fr 1fr 1fr' 试试。入口卡片变成三列后,最明显的变化不是代码复杂了,而是每个卡片能分到的宽度变少了。你平时更常做两列入口,还是三列入口?

完整代码

import { LengthMetrics } from '@kit.ArkUI';

class LazyGridCard {
  title: string = '';
  desc: string = '';
  color: string = '';

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

@Entry
@Component
struct ArkUILazyGridLayoutDemo {
  private cards: LazyGridCard[] = [
    new LazyGridCard('消息', '统一收口', '#2563EB'),
    new LazyGridCard('日程', '今天先看', '#0F766E'),
    new LazyGridCard('文件', '最近打开', '#7C3AED'),
    new LazyGridCard('收藏', '常用入口', '#C2410C'),
    new LazyGridCard('审批', '待处理 8', '#1D4ED8'),
    new LazyGridCard('统计', '本周概览', '#047857'),
    new LazyGridCard('会员', '权益配置', '#9333EA'),
    new LazyGridCard('设置', '偏好调整', '#B45309'),
    new LazyGridCard('帮助', '快速查找', '#334155'),
    new LazyGridCard('反馈', '问题记录', '#BE123C'),
    new LazyGridCard('账单', '支出明细', '#0369A1'),
    new LazyGridCard('草稿', '继续编辑', '#15803D')
  ];

  @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
  cardItem(item: LazyGridCard, index: number) {
    Column({ space: 8 }) {
      Text(`${index + 1}`)
        .width(34)
        .height(34)
        .fontSize(15)
        .fontWeight(700)
        .fontColor('#FFFFFF')
        .textAlign(TextAlign.Center)
        .backgroundColor(item.color)
        .borderRadius(8)

      Text(item.title)
        .fontSize(15)
        .fontWeight(700)
        .fontColor('#0F172A')

      Text(item.desc)
        .fontSize(12)
        .fontColor('#64748B')
    }
    .width('100%')
    .height(118)
    .justifyContent(FlexAlign.Center)
    .alignItems(HorizontalAlign.Center)
    .backgroundColor('#FFFFFF')
    .border({ width: 1, color: '#E2E8F0' })
    .borderRadius(8)
  }

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

        Text('数据一多,就别一次性全摆上来')
          .width('100%')
          .fontSize(22)
          .fontWeight(700)
          .fontColor('#111827')

        Text('这一页只看 LazyVGridLayout 的基础样子:固定高度滚动区域、列模板、行列间距和多列卡片。这里不做无限加载,也不讲数据源增删。')
          .width('100%')
          .fontSize(14)
          .fontColor('#64748B')
          .lineHeight(22)

        Column({ space: 12 }) {
          this.sectionTitle('columnsTemplate 先把列数定下来', 'LazyVGridLayout 用 columnsTemplate 描述纵向网格列宽。这里写成 1fr 1fr,也就是两列等宽。')

          WaterFlow() {
            LazyVGridLayout() {
              ForEach(this.cards, (item: LazyGridCard, index: number) => {
                this.cardItem(item, index)
              }, (item: LazyGridCard) => item.title)
            }
            .columnsTemplate('1fr 1fr')
            .rowsGap(LengthMetrics.vp(10))
            .columnsGap(LengthMetrics.vp(10))
            .width('100%')
          }
          .height(330)
          .width('100%')
          .padding(10)
          .backgroundColor('#FFFFFF')
          .border({ width: 1, color: '#DBEAFE' })
          .borderRadius(8)
        }
        .width('100%')
        .padding(16)
        .backgroundColor('#EFF6FF')
        .borderRadius(8)

        Column({ space: 12 }) {
          this.sectionTitle('行列间距不要混着猜', 'rowsGap 管上下间距,columnsGap 管左右间距。入口卡片这种结构,先把间距写稳,视觉会清楚很多。')

          WaterFlow() {
            LazyVGridLayout() {
              ForEach(this.cards.slice(0, 6), (item: LazyGridCard, index: number) => {
                this.cardItem(item, index)
              }, (item: LazyGridCard) => item.title)
            }
            .columnsTemplate('1fr 1fr 1fr')
            .rowsGap(LengthMetrics.vp(12))
            .columnsGap(LengthMetrics.vp(8))
            .width('100%')
          }
          .height(250)
          .width('100%')
        }
        .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个月内不可修改。