HarmonyOS ArkTS 创建网格 Grid/GridItem:写得顺、适配稳、滚动不卡的那套方法

HarmonyOS ArkTS 创建网格 Grid/GridItem:写得顺、适配稳、滚动不卡的那套方法

鸿蒙第四期开发者活动

网格布局(Grid)不是"Row/Column 的升级版",它更像是你在做 九宫格、相册墙、商品卡片 时的"标准答案":用"行 + 列"把容器切成一个个单元格,然后把内容放进去。developer.huawei.com+1

这篇我按项目里真会遇到的顺序写:先把概念讲透,再给你三种最常见的写法(固定网格 / 可滚动网格 / 自适应网格),最后再讲几个一踩就痛的坑。


1)Grid 和 GridItem 到底是什么关系?

  • Grid():网格容器 ,负责"行列怎么分、间距多大、怎么滚动、怎么排列"。developer.huawei.com+1
  • GridItem():网格里的单元格项目 ,每一块内容都应该放在 GridItem 里。官方也强调 Grid 的子组件是 GridItem。developer.huawei.com+1

你可以把它理解成: Grid 负责"铺地砖",GridItem 负责"在每块砖上放东西"。


2)先把"网格怎么分"的思路掰直:rowsTemplate / columnsTemplate

Grid 最核心的两句话就是:

  • rowsTemplate(...):定义有几行,每一行占多少"比例"
  • columnsTemplate(...):定义有几列 ,每一列占多少"比例"Gitee+1

它们的值通常是这样的字符串:

arduino 复制代码
 .columnsTemplate('1fr 1fr 1fr')
 .rowsTemplate('1fr 2fr')

这里的 fr 可以理解为"份数"(比例单位):

  • 1fr 1fr 1fr = 三列等分
  • 1fr 2fr = 两行,第二行高度是第一行的 2 倍Gitee+1

行列间距:rowsGap / columnsGap

  • rowsGap(n):行与行之间的间距
  • columnsGap(n):列与列之间的间距Gitee+1

3)最常用的三种网格写法(基本覆盖 80% 页面)

A. 固定网格:行列都写死(最稳、最适合"九宫格/计算器/日历")

这种写法最"可控":几行几列固定,布局结构一眼就能看懂。

scss 复制代码
 @Entry
 @Component
 struct GridFixedDemo {
   build() {
     Column({ space: 12 }) {
       Text('固定网格:2 行 x 3 列').fontSize(16).fontWeight(FontWeight.Medium)
 ​
       Grid() {
         ForEach([1,2,3,4,5,6], (n: number) => {
           GridItem() {
             Text(`${n}`)
               .width('100%')
               .height('100%')
               .fontSize(18)
               .fontWeight(FontWeight.Bold)
               .textAlign(TextAlign.Center)
               .backgroundColor(0xFFFFFFFF)
               .borderRadius(12)
           }
         }, (n: number) => `${n}`)
       }
       .rowsTemplate('1fr 1fr')
       .columnsTemplate('1fr 1fr 1fr')
       .rowsGap(10)
       .columnsGap(10)
       .height(220)
       .width('100%')
     }
     .padding(12)
     .backgroundColor(0xFFF5F6F8)
     .width('100%')
     .height('100%')
   }
 }

这种"行列都设置"的场景,结构固定、好设计、好测 UI。官方创建网格文档也主要围绕 rowsTemplate/columnsTemplate 来说明。Gitee+1


B. 可滚动网格:只设置一个模板,让 Grid 自己滚动(文件管理/商品流最常见)

这个点很多人第一次会误会: Grid 并不是一定要自己套 Scroll。 当你"只设置一个维度模板"时,Grid 往往就能形成滚动网格(官方和社区都把这当成常用方案)。CSDN博客+1

竖向滚动网格(常用:只设置 columnsTemplate)
scss 复制代码
 @Entry
 @Component
 struct GridScrollVerticalDemo {
   @State items: number[] = Array.from({ length: 60 }, (_, i) => i + 1)
 ​
   build() {
     Grid() {
       ForEach(this.items, (n: number) => {
         GridItem() {
           Column({ space: 6 }) {
             // 模拟"商品卡片"
             Rect().width('100%').height(70).fill(0xFFEAF2FF).radius(12)
             Text(`商品 #${n}`).fontSize(14)
             Text('¥ 99.00').fontSize(12).fontColor(0xFF888888)
           }
           .padding(10)
           .backgroundColor(0xFFFFFFFF)
           .borderRadius(12)
         }
       }, (n: number) => `${n}`)
     }
     .columnsTemplate('1fr 1fr')   // 两列
     .columnsGap(10)
     .rowsGap(10)
     .padding(12)
     .backgroundColor(0xFFF5F6F8)
     .width('100%')
     .height('100%')
   }
 }

你会发现:项目多到超出屏幕后,Grid 会按列规则继续排,页面自然就变成"可滚动商品流"。


C. "看起来像自适应"的网格:优先用 Responsive Grid(GridRow/GridCol)

如果你要做"跨设备适配",例如:

  • 手机 2 列
  • 平板 4 列
  • 大屏 6 列

这类更推荐使用 响应式网格系统 GridRow/GridCol (文档里把它归为 Responsive Grid Layout)。developer.huawei.com+1

你这次问的是 Grid/GridItem 的创建,我就先把原理讲透;如果你要做"断点适配",我可以再给你一篇专门写 GridRow/GridCol 的"手机/平板一套代码适配"的实战模板。


4)GridItem 里到底放什么?(项目里最常见的 3 种卡片结构)

你可以把 GridItem 当成一个"小容器",里面爱怎么排怎么排:

  1. 图片 + 标题 + 价格(电商卡片)
  2. 图标 + 文案(九宫格入口)
  3. 封面图 + 标签(相册/视频墙)

关键是:GridItem 外面不用再套一堆布局容器去算宽高 ,网格的宽高由模板决定,你只要让子内容 width('100%')、卡片圆角、padding 做舒服就行。


5)性能和渲染:别等卡了才想起优化

当你网格项很多(比如几百上千)时,建议关注两点:

① 优先考虑懒加载思路(LazyForEach)

OpenHarmony 的文档里提到:GridItem 与 LazyForEach 配合时,子组件在 GridItem 创建时创建;而配合 ForEach/if 或父组件为 Grid 时,子组件在布局时创建。Gitee

简单说就是:

  • 数据量大:考虑 LazyForEach(减少一次性创建的压力)
  • 数据量小:ForEach 足够

② 让每个 item 有稳定 key

ForEach(data, builder, keyFn) 里的 keyFn 不要省: 稳定 key 能减少"刷新时整片重建",滚动和更新都会更顺。


6)几个一踩就中招的坑(写 Grid 时很常见)

坑 1:GridItem 不铺满格子

很多人写 GridItem 只放 Text,结果格子看起来"空、挤、对不齐"。 经验做法是:卡片容器本身设 width('100%')、内容设 padding,视觉会稳。

坑 2:间距没设导致"挤成一坨"

rowsGap / columnsGap 不写默认就是 0,网格会贴得很紧。Gitee+1

坑 3:把 Grid 当成万能布局

Grid 很强,但它擅长的是"规则二维"。 像"一个卡片左图右文,下方再有按钮"的复杂自由布局,通常是 GridItem 内部用 Row/Column/Flex/Stack 组合,而不是用 Grid 去硬拼结构。


7)你可以直接拿去做博客的收尾总结

  • Grid/GridItem 适合"规则二维内容展示":九宫格、卡片墙、相册、商品流。developer.huawei.com+1
  • rowsTemplate/columnsTemplate 决定"网格怎么分",rowsGap/columnsGap 决定"网格舒不舒服"。Gitee+1
  • 数据量大时,关注稳定 key 和懒加载(LazyForEach),滚动体验差距非常明显。Gitee
相关推荐
养猪喝咖啡2 小时前
ArkTS 文本输入组件(TextInput)详解
harmonyos
养猪喝咖啡2 小时前
HarmonyOS ArkTS 页面导航(Navigation)全面介绍
harmonyos
养猪喝咖啡2 小时前
HarmonyOS ArkTS 从 Router 到 Navigation 的迁移指南
harmonyos
养猪喝咖啡2 小时前
HarmonyOS ArkTS Stack 实战:做一个“悬浮按钮 + 遮罩弹层 + 底部菜单”的完整小项目
harmonyos
Archilect2 小时前
从几何到路径:ArkUI 下的双层容器、缩放偏移与抛掷曲线设计
harmonyos
子榆.3 小时前
Flutter 与开源鸿蒙(OpenHarmony)性能调优实战:从启动速度到帧率优化的全链路指南
flutter·开源·harmonyos
子榆.3 小时前
Flutter 与开源鸿蒙(OpenHarmony)安全加固实战:防逆向、防调试、数据加密全攻略
flutter·开源·harmonyos
低调电报4 小时前
我的第一个开源项目:鸿蒙分布式“口袋健身”教练
分布式·开源·harmonyos
子榆.4 小时前
Flutter 与开源鸿蒙(OpenHarmony)深度集成实战(二):实现跨设备分布式数据同步
flutter·开源·harmonyos