HarmonyOS ArkTS 网格布局(Grid Layout)详解

40 阅读5分钟

HarmonyOS ArkTS 网格布局(Grid Layout)详解

鸿蒙第四期开发者活动

网格布局是界面布局中一个特别有用的方式,尤其当你希望把内容平铺成 规则行列结构 时,比如 相册图库、商品卡片列表、信息密集型仪表盘 等场景,一旦掌握了网格布局,它能让界面组织变得非常轻松。developer.huawei.com


一、什么是网格布局

在 ArkTS 的声明式 UI 体系里,Grid 容器 是一种二维布局方式,它不像 Row/Column 只有一条轴(水平/垂直),而是把页面划分成 固定的行和列。 你可以通过定义行、列的“分数”/比例,配合间距、单元格间隔等配置,让子组件在网格中均匀排列。Gitee

从设计角度看:

  • 它能实现 规则的二维结构
  • 子组件直接按格子位置分布
  • 适合大批量、等间隔元素展示
  • 是响应式布局里重要的一环,能适应不同尺寸屏幕developer.huawei.com

二、Grid 能解决什么问题

想象以下场景:

✔ 一堆商品卡片需要按 3 列排列 ✔ 图片墙需要自动按屏幕宽度排布 ✔ 你希望某些项目跨越多列或多行

如果用 Row/Column 嵌套写,会很绕:

 RowColumnRowColumn → ...

而 Grid 只需要一句:

 按行列规则定义网格 → 把所有子项放进去即可

它的核心在于将界面拆分为有规律的 网格单元,然后让内容自动适配这些格子,从而减少嵌套层级和写样式的成本。Gitee


三、怎么写基本的 Grid

最简单的网格结构长这样:

 @Entry
 @Component
 struct GridExample {
   build() {
     Grid() {
       GridItem() { Text("1") }
       GridItem() { Text("2") }
       GridItem() { Text("3") }
       GridItem() { Text("4") }
       GridItem() { Text("5") }
       GridItem() { Text("6") }
     }
     .rowsTemplate("1fr 1fr")          // 两行
     .columnsTemplate("1fr 1fr 1fr")   // 三列
     .rowsGap(10)                      // 行间距
     .columnsGap(10)                   // 列间距
     .width('100%')
     .height(300);
   }
 }

解释一下:

  • Grid() 是容器
  • GridItem() 是单个网格单元
  • rowsTemplate("1fr 1fr") 定义了 两行
  • columnsTemplate("1fr 1fr 1fr") 定义了 三列
  • "fr"fraction(分数)单位,表示比例空间
  • rowsGapcolumnsGap 则控制行列之间的间隔

这样写出来,是一个 2 × 3 的网格,每个格子的空间按行列权重平均分配。Gitee


四、rowsTemplate / columnsTemplate 的细节

1) 基于比例的布局

你可以写:

  • "1fr 1fr 1fr" → 三等分
  • "2fr 1fr" → 第一行/列占 2 份宽度,第二份为 1 份

比如:

 .columnsTemplate("2fr 1fr")
 .rowsTemplate("1fr 2fr")

上面定义的是:

  • 两列宽度比例是 2:1
  • 两行高度比例是 1:2

这种写法非常适合你在视觉上想要某些格子更大、更醒目。Gitee


五、网格间距和样式常用属性

属性作用
rowsGap(value)控制每一行之间的垂直间距
columnsGap(value)控制每一列之间的水平间距
gridStyle(...)给整个网格增加背景/边框/边距等样式

示例:

 Grid()
   .columnsTemplate("1fr 1fr 1fr")
   .rowsTemplate("1fr 1fr")
   .columnsGap(12)
   .rowsGap(8)
   .gridStyle({
     backgroundColor: Color.White,
     borderRadius: 8,
   });

注意:

  • 间距不是自动的,你必须主动设置,否则网格项之间挨得很近

因为每个行/列是等分的,所以合理设置间距能让 UI 看起来更清爽。kitemetric.com


六、什么时候用 Grid 比较合适

合适的场景包括:

1. 图片墙 / 图库

比如一个 3 列图库,每个图片都统一大小,这种情况最适合 Grid。

2. 商品卡片列表

你希望商品卡片在横屏/竖屏下都能等宽分布。

3. 仪表盘 / 统计面板

这种卡片型的结构很多时候是规则网格,看起来整齐统一。

不是所有网格都要用 Grid

如果你的布局只是简单的一行三列按钮,其实 Row + SpaceBetween 即可;只有当 UI 是“多行多列”的规则结构时,Grid 才真正凸显它的价值。


七、进阶:动态数据 + Grid

在实际项目中,我们往往不是手敲每个 GridItem,而是通过数组动态生成。典型写法是配合 ForEach 使用:

 Grid() {
   ForEach(this.items, (item) => {
     GridItem() {
       Text(item.title)
         .fontSize(14)
         .fontColor(Color.Black);
     }
   })
 }
 .rowsTemplate("repeat(3, 1fr)") // 重复三等分
 .columnsGap(12)
 .rowsGap(12)

相较于静态写法,动态渲染让你能轻松应对列表数据变化kitemetric.com


八、响应式适配(高级)

官方也让 Grid 支持一种响应式适配思路(类似 CSS Grid + Breakpoints 概念):可以按屏幕尺寸自动调整列数。比如:

  • 屏幕小 → 2 列
  • 屏幕大 → 4 列

官方文档里提到在 GridRow/GridCol 的 响应式网格系统。[openharmony docs 镜像](它划分断点、可按设备宽度自动调整布局)。developer.huawei.com

虽然具体 API 可能需要看 breakpoints 的定义方式,但核心思路是:

先定义断点,再定义在各个断点下 columnsTemplate,最后让系统按屏幕宽度自动切换布局规则。

这种写法在多屏设备(手机/平板/大屏)中用得非常多。


九、实战小建议

下面这些是我做 UI 时经常踩坑的问题,也是你在用 Grid 时绝大多数能遇到的:

1. 不要忘记设置 rowsTemplatecolumnsTemplate

如果没有设置任何行/列模板,Grid 不会按你预期展示。 它不会像 Flex 那样自动缩放每个子节点 —— 它本质上是按照模板去布局的Gitee


2. 间距一定要设置

尤其是 columnsGap / rowsGap,不设置的话默认是 0,视觉上看起来会很挤。


3. 配合 Scroll 一起用

如果你的网格内容很多,记得把 Grid 放在一个可滚动的组件(如 Scroll)里,这样超出屏幕的内容才会滚动,否则会压缩得很难看。


十、总结(一句话)

Grid 布局是规则二维布局的最优解:它让你用一套模板声明出规律性的行列结构,再把内容填进去,而不用写一堆嵌套容器,适合展示“表格式、图库式、卡片式”的界面。

当你在项目里需要让元素在横纵方向都有一致的定位规则时,Grid 是最简洁可靠的工具。developer.hu