【共创季稿事节】鸿蒙原生 ArkTS 布局精讲:Grid 组件实现九宫格布局
鸿蒙原生 ArkTS 布局精讲:Grid 组件实现九宫格布局(HarmonyOS NEXT API 24)



一、引言
1.1 为什么是九宫格?
九宫格(3×3 Grid)是移动端 UI 中最经典、最基础的网格布局形态。从手机桌面图标排列、相机滤镜选择、密码手势解锁,到功能入口矩阵("我的"页面中的九宫格功能模块),九宫格无处不在。它是每一个鸿蒙开发者必须掌握的基础布局能力。
在 HarmonyOS NEXT 中,实现九宫格最优雅的方式就是使用 ArkUI 提供的 Grid 容器组件。本文将以一个完整的九宫格示例项目为主线,从零开始讲解 Grid 组件的核心 API、布局原理、样式定制和工程最佳实践,帮助读者彻底掌握鸿蒙原生网格布局。
1.2 目标读者
本文面向以下读者:
- 刚接触 HarmonyOS NEXT 开发、想系统学习 ArkTS 布局的初学者
- 已有前端或 Android/iOS 经验、正在迁移到鸿蒙生态的开发者
- 希望深入理解 Grid 组件 API 细节、追求高性能布局的中级开发者
1.3 技术栈一览
| 技术 | 版本 / 说明 |
|---|---|
| HarmonyOS NEXT | API 24(最新稳定版) |
| 声明式开发语言 | ArkTS(基于 TypeScript) |
| UI 框架 | ArkUI 全局组件(无需 import) |
| 构建工具 | hvigor |
| 开发 IDE | DevEco Studio NEXT |
二、Grid 组件概述
2.1 什么是 Grid?
Grid(网格容器)是 ArkUI 提供的一种 二维布局容器,能够将子组件按行和列排列成规则的网格结构。与传统的线性布局(Column/Row)相比,Grid 天然支持横纵两个方向的排列控制,非常适合实现九宫格、相册缩略图、商品列表等需要规整排列的场景。
2.2 Grid 与 Flex / List 的对比
为了帮助读者理解 Grid 的定位,下面将它与鸿蒙中其他常见布局容器进行对比:
| 特性 | Grid | Column / Row | Flex | List |
|---|---|---|---|---|
| 布局维度 | 二维(行+列) | 一维(单方向) | 一维(单方向) | 一维(滚动列表) |
| 行列控制 | columnsTemplate + rowsTemplate |
无 | 无 | 无 |
| 自动换行 | 支持 | 不支持 | 支持(wrap) | 不支持 |
| 滚动 | 可启用 | 不原生支持 | 不原生支持 | 专为滚动优化 |
| 子组件间距 | columnsGap + rowsGap |
space 参数 |
gap |
space |
| 适用场景 | 网格 / 表格 / 九宫格 | 线性排列 | 流式布局 | 长列表 |
总结:如果你的 UI 是"方方正正"的格子形态,Grid 是第一选择,而非 Column 多层嵌套或 Flex 的折行方案。
2.3 Grid 在 API 24 中的新特性
HarmonyOS NEXT API 24 对 Grid 组件做了进一步优化和增强,主要包括:
- 更高效的懒加载机制:当 Grid 包含大量子项(如 1000+ GridItem)时,API 24 优化了不可见项的回收策略,减少了 GPU 渲染压力。
- 跨端适配增强:Grid 的
columnsTemplate和rowsTemplate现在支持更灵活的单位组合,包括%、px、vp与fr的混合使用。 - 新的子组件对齐能力:
GridItem新增了alignSelf属性,允许单个格子覆盖容器的默认对齐方式。 - 动画支持:Grid 的
columnsGap和rowsGap现在可以参与动画过渡,实现间距动态变化的流畅效果。 - 无障碍访问增强:Grid 和 GridItem 自动获得了无障碍焦点遍历顺序,无需开发者手动设置
tabIndex。
本文的示例将基于 API 24 编写,充分利用这些新特性。
三、项目搭建与工程结构
3.1 创建项目
使用 DevEco Studio NEXT 创建一个新的 HarmonyOS 工程:
- 打开 DevEco Studio,点击 Create Project
- 选择 Empty Ability 模板
- 配置项目名称(如
app014)、包名、存储路径 - 在 Compatible SDK 中选择 API 24
- 点击 Finish 完成创建
3.2 项目结构说明
创建完成后,项目的主要结构如下:
app014/
├── entry/
│ ├── src/main/
│ │ ├── ets/
│ │ │ ├── entryability/ # Ability 生命周期
│ │ │ │ └── EntryAbility.ets
│ │ │ └── pages/ # 页面目录
│ │ │ └── Index.ets # 主页面(九宫格)
│ │ ├── module.json5 # 模块配置
│ │ └── resources/ # 资源文件
│ ├── build-profile.json5 # 模块构建配置
│ └── oh-package.json5 # 依赖管理
├── build-profile.json5 # 工程构建配置
├── oh-package.json5 # 工程依赖
└── hvigor/
└── hvigor-config.json5 # hvigor 配置
我们所有的 UI 代码都集中在 entry/src/main/ets/pages/Index.ets 中,这也是本文重点讲解的文件。
四、完整代码实现
4.1 数据模型定义
首先,我们需要定义九宫格中每个格子的数据结构。在 ArkTS 中,使用 interface 来声明类型:
/**
* 九宫格每一项的数据模型
* id : 唯一标识(1~9)
* label : 格子里显示的中文数字(一~九)
* color : 格子的背景色
*/
interface GridCell {
id: number;
label: string;
color: ResourceColor;
}
id:数字编号,同时用作 ForEach 的键值(key),保证列表 diff 算法高效运行。label:显示在格子中的文字,这里使用中文数字 “一” 到 “九”,增加文化特色。color:背景色,类型为ResourceColor(ArkTS 中表示颜色值的类型),可以是十六进制字符串、RGB/RGBA 或 Resource 引用。
4.2 页面结构与 @State 数据源
使用 @Entry 和 @Component 装饰器声明页面组件:
@Entry
@Component
struct Index {
@State cells: GridCell[] = [
{ id: 1, label: '一', color: '#FF6B81' },
{ id: 2, label: '二', color: '#5B8FF9' },
{ id: 3, label: '三', color: '#5AD8A6' },
{ id: 4, label: '四', color: '#F6BD16' },
{ id: 5, label: '五', color: '#7262FD' },
{ id: 6, label: '六', color: '#FF9D4D' },
{ id: 7, label: '七', color: '#B37FEB' },
{ id: 8, label: '八', color: '#3DC27F' },
{ id: 9, label: '九', color: '#F56C6C' },
];
// ... build() 方法
}
关键知识点:
@Entry:标记该组件为页面的入口组件,系统会自动为它创建页面路由。@Component:声明这是一个可复用的自定义组件。@State:装饰的状态变量。当cells数组发生变化时,UI 会自动重新渲染。- 9 种对比鲜明的颜色:红、蓝、绿、黄、紫、橙、浅紫、翠绿、朱红,每种颜色都与对应的中文数字配合,视觉层次分明。
4.3 build() 方法:搭建三层结构
在 ArkTS 中,UI 是由 build() 方法中的声明式代码"描述"出来的。我们的页面采用从上到下的三层结构:
Column(全屏渐变背景)
├── Text 区域(标题 + 副标题)
├── Grid 区域(核心九宫格,3×3)
└── Row 区域(底部提示条)
4.3.1 最外层:Column + 渐变背景
build() {
Column() {
// ... 子组件
}
.width('100%')
.height('100%')
.linearGradient({
direction: GradientDirection.Bottom,
colors: [['#F0F4F8', 0.0], ['#E8ECF2', 1.0]]
})
.alignItems(HorizontalAlign.Center)
}
width('100%')和height('100%'):Column 铺满整个屏幕。linearGradient:顶部浅灰蓝#F0F4F8渐变到底部#E8ECF2,比纯白色背景更柔和、更有质感。alignItems(HorizontalAlign.Center):所有子组件水平居中。
4.3.2 标题区域
Text('✦ 九宫格布局(3×3 Grid)')
.fontSize(22)
.fontWeight(FontWeight.Bold)
.fontColor('#2C3E50')
.margin({ top: 32, bottom: 8 })
.textAlign(TextAlign.Center)
Text('Grid + columnsTemplate/rowsTemplate')
.fontSize(14)
.fontColor('#95A5A6')
.margin({ bottom: 24 })
- 主标题使用 22fp 加粗字体,深灰蓝色
#2C3E50。 - 副标题 14fp,浅灰色
#95A5A6,作为技术词汇的补充说明。
4.3.3 核心:Grid 九宫格
这是整个页面的核心,也是本文重点讲解的部分:
Grid() {
ForEach(this.cells, (item: GridCell) => {
GridItem() {
Column() {
Text(item.id.toString())
.fontSize(28)
.fontWeight(FontWeight.Bold)
.fontColor('#FFFFFF')
Text(item.label)
.fontSize(16)
.fontColor('rgba(255, 255, 255, 0.85)')
.margin({ top: 6 })
}
.width('100%')
.height('100%')
.justifyContent(FlexAlign.Center)
.alignItems(HorizontalAlign.Center)
}
.width('100%')
.height('100%')
.backgroundColor(item.color)
.borderRadius(12)
.onClick(() => {
console.info(`[九宫格] 点击了第 ${item.id} 格:${item.label}`);
})
}, (item: GridCell) => item.id.toString())
}
.columnsTemplate('1fr 1fr 1fr')
.rowsTemplate('1fr 1fr 1fr')
.columnsGap(8)
.rowsGap(8)
.width('90%')
.height(360)
.borderRadius(16)
.padding(8)
.backgroundColor('#F5F7FA')
.shadow({
radius: 12,
color: 'rgba(0, 0, 0, 0.08)',
offsetX: 0,
offsetY: 4
})
这里集中呈现了 Grid 的绝大多数核心 API,下面逐一拆解。
4.3.4 底部提示区域
Row() {
Text('💡 点击任意格子 → 查看 HiLog 日志')
.fontSize(14)
.fontColor('#7F8C8D')
}
.margin({ top: 24 })
.padding({ top: 12, bottom: 12, left: 20, right: 20 })
.backgroundColor('#ECF0F1')
.borderRadius(20)
- 浅灰色胶囊形提示条,提示用户点击格子并通过 HiLog 查看日志输出。
- 这种"交互 + 反馈"的设计能帮助学习者立刻验证代码是否按预期运行。
五、Grid 核心 API 深度解析
本章节对示例中使用的每一个 Grid API 进行详细解读,并结合源码说明其设计意图。
5.1 columnsTemplate:列模板
.columnsTemplate('1fr 1fr 1fr')
columnsTemplate 定义了 Grid 的列结构,是一个以空格分隔的字符串,每个 token 代表一列的宽度。
支持的宽度单位:
| 单位 | 说明 | 示例 |
|---|---|---|
fr |
比例单位(fraction),按比例分配剩余空间 | '1fr 1fr 1fr' = 三等分 |
px |
物理像素 | '100px 1fr 1fr' |
vp |
虚拟像素(密度无关像素) | '80vp 1fr 1fr' |
% |
父容器宽度的百分比 | '30% 40% 30%' |
auto |
自适应内容宽度 | 'auto 1fr 1fr' |
在九宫格中的含义:'1fr 1fr 1fr' 表示 Grid 容器的宽度被三等分,每列占据 1 份可用空间。如果 Grid 宽度是屏幕宽度的 90%(通过 .width('90%') 设置),那么每列宽度就是 90% × 33.33% = 30% 的屏幕宽度。
实用技巧:如果要实现"中间宽、两侧窄"的布局,可以使用 columnsTemplate('1fr 2fr 1fr'),中间列会自动占据两倍的宽度。
5.2 rowsTemplate:行模板
.rowsTemplate('1fr 1fr 1fr')
与 columnsTemplate 对称,rowsTemplate 定义 Grid 的行高结构。'1fr 1fr 1fr' 表示 Grid 的高度被三等分,每行占据 1 份可用空间。
缺省行为:如果只设置 columnsTemplate 而不设置 rowsTemplate,Grid 会根据子项数量自动计算行数,并使用 auto 作为行高(即每行高度由子内容撑开)。对于九宫格这种需要严格等高的场景,必须同时设置 rowsTemplate。
5.3 columnsGap 与 rowsGap:间距控制
.columnsGap(8)
.rowsGap(8)
columnsGap:列与列之间的间距,单位 vp。这里设为 8vp,在九宫格中表现为每个格子之间的水平间隔。rowsGap:行与行之间的间距,单位 vp。设为 8vp,表现为垂直间隔。
等距还是非等距? 在九宫格中,通常 columnsGap 和 rowsGap 设置相同的值,以保持视觉对称。但在某些特殊场景(如照片墙布局)中,可以让水平间距和垂直间距不同,创造独特的节奏感。
5.4 ForEach:高效循环渲染
ForEach(this.cells, (item: GridCell) => {
// ... 渲染每个 GridItem
}, (item: GridCell) => item.id.toString())
ForEach 是 ArkTS 中用于列表渲染的内置组件,它接收三个参数:
- 数据源(
this.cells):要遍历的数组。 - 内容生成器(箭头函数):对每项数据,返回对应的 UI 组件树。
- 键值生成器(选填):为每项生成唯一的键(key),用于列表 diff 优化。
为什么要提供键值生成器?
当数据源发生变化时(如增删排序),ArkUI 框架需要知道哪些项是新插入的、哪些是删除的、哪些只是位置变化。如果没有键值,框架只能从头到尾重新渲染所有项,性能较差。有了稳定的键值(这里使用 item.id),框架可以精准定位变化,只更新受影响的部分。
注意:键值必须是稳定且唯一的。使用数组索引(index)作为键值是不推荐的,因为在数组增删后索引会变化,导致 diff 算法误判。
5.5 GridItem:网格中的最小单元
GridItem() {
// 每个格子的内容
}
.width('100%')
.height('100%')
.backgroundColor(item.color)
.borderRadius(12)
.onClick(() => { ... })
GridItem 是 Grid 的直接子组件,代表网格中的一个单元格。它继承自 ArkUI 的基础组件,因此可以设置宽高、背景色、圆角、阴影、点击事件等。
重要设计原则:
- GridItem 的默认宽高受到 Grid 的行列模板约束,设置
width('100%')和height('100%')可以让它填满整个格子区域。 - GridItem 内部只能有一个根组件(这里我们使用 Column),如果需要在格子中放置多个元素,必须嵌套在一个容器组件中。
5.6 shadow:阴影与立体感
.shadow({
radius: 12,
color: 'rgba(0, 0, 0, 0.08)',
offsetX: 0,
offsetY: 4
})
shadow 属性为 Grid 容器添加了外阴影效果,参数说明:
| 参数 | 值 | 含义 |
|---|---|---|
radius |
12 | 阴影模糊半径,越大越模糊扩散 |
color |
rgba(0,0,0,0.08) |
阴影颜色,8% 不透明度的黑色 |
offsetX |
0 | 水平偏移(正数向右) |
offsetY |
4 | 垂直偏移(正数向下),4vp 的下沉阴影 |
视觉效果:Grid 容器仿佛悬浮在背景之上,增强了页面的层次感和精致度。注意阴影透明度要低(8%),否则会显得过于突兀。
5.7 borderRadius:圆角
// Grid 外容器圆角
.borderRadius(16)
// 每个 GridItem 格子圆角
.borderRadius(12)
- Grid 容器使用
16vp圆角,较大的圆角让整个九宫格区块更柔和。 - 每个 GridItem 使用
12vp圆角,略小于外容器,形成"内嵌"的视觉层次。 - 圆角 + 背景色 + 阴影的组合是移动端"卡片设计"的三要素。
5.8 linearGradient:线性渐变
.linearGradient({
direction: GradientDirection.Bottom,
colors: [['#F0F4F8', 0.0], ['#E8ECF2', 1.0]]
})
linearGradient 为容器填充线性渐变背景:
direction:渐变方向。GradientDirection.Bottom表示从上到下渐变。colors:颜色断点数组。每个元素是[颜色值, 位置]的元组。['#F0F4F8', 0.0]表示起点颜色,['#E8ECF2', 1.0]表示终点颜色。
为什么使用渐变而不是纯色? 纯白背景在手机屏幕上显得单调乏味,微妙的灰蓝色渐变既不影响可读性,又能提升页面的视觉品质。
六、布局原理深入分析
6.1 九宫格的尺寸计算
以一张 360vp 宽、360vp 高的 Grid 容器为例,九宫格的尺寸计算如下:
已知:
Grid 宽度 = 90% 屏幕宽度 ≈ 324vp(假设屏幕宽 360vp)
Grid 高度 = 360vp
columnsGap = 8vp(2 个间距)
rowsGap = 8vp(2 个间距)
padding = 8vp(左右各 8vp,上下各 8vp)
可用宽度 = 324 - 8×2 - 8×2 = 292vp
每列宽度 = 292 / 3 ≈ 97.3vp
可用高度 = 360 - 8×2 - 8×2 = 328vp
每行高度 = 328 / 3 ≈ 109.3vp
因此每个 GridItem 的实际尺寸约为 97vp × 109vp,这是一个接近正方形的矩形。如果希望 Grid 是完美的正方形,可以将 Grid 的宽高设置为相同的值,或者使用 aspectRatio 约束。
6.2 fr 单位的工作原理
fr(fraction,比例单位)是 Grid 布局中最灵活的单位。它的计算方式如下:
- 先减去所有固定宽度(px、vp、% 列)和间距(columnsGap)
- 将剩余可用空间按
fr值的比例分配给各列
例如,columnsTemplate('100px 1fr 2fr') 的计算过程:
总宽度 = 324vp
固定列 = 100px(假设 ≈ 50vp)
间距 = 8vp × 2 = 16vp
剩余 = 324 - 50 - 16 = 258vp
比例 = 1fr : 2fr,共 3 份
列 1(1fr)= 258 / 3 × 1 = 86vp
列 2(2fr)= 258 / 3 × 2 = 172vp
正是因为 fr 的单位具有"分配剩余空间"的特性,'1fr 1fr 1fr' 才能完美实现三等分,无论容器宽度如何变化。
6.3 Grid 的自动换行机制
当 GridItem 的数量超过 columnsTemplate × rowsTemplate 的容量时,Grid 默认会自动增加行数来容纳额外的子项。例如,如果设置了 columnsTemplate('1fr 1fr 1fr') 和 rowsTemplate('1fr 1fr 1fr'),但添加了 12 个 GridItem,那么 Grid 会自动变为 3 列 × 4 行。
要禁用自动增加行数,可以设置 rowsTemplate 为固定模式,并配合 Scroll 组件来实现滚动。对于九宫格,我们恰好是 3×3=9 项,刚好填满,没有溢出问题。
七、最佳实践与性能优化
7.1 数据驱动 UI
这是一个重要的 ArkTS 编程范式:永远通过修改数据来驱动 UI 变化,而非直接操作 DOM。
✅ 推荐做法:
@State cells: GridCell[] = [...];
// 修改数据
this.cells[0] = { id: 1, label: '新值', color: '#FF0000' };
// UI 自动更新
❌ 不推荐(在 ArkTS 中也不允许):
// 不存在类似 setText() / setColor() 的直接 DOM 操作
7.2 使用稳定的键值
在 ForEach 的第三个参数中提供稳定的键值:
ForEach(this.cells, (item) => { ... }, (item) => item.id.toString())
为什么重要:当数组发生插入、删除、排序时,框架通过键值对比来决定哪些 GridItem 需要重建、哪些可以复用。使用 id 而非索引作为键值,可以避免不必要的 DOM 重建,提升列表性能。
7.3 Grid 的懒加载(LazyForEach)
当九宫格扩展为大量数据时(如 100×100 网格),应使用 LazyForEach 替代 ForEach:
Grid() {
LazyForEach(this.dataSource, (item: GridCell) => {
GridItem() { /* ... */ }
}, (item: GridCell) => item.id.toString())
}
.columnsTemplate('1fr 1fr 1fr')
// ...
LazyForEach 只渲染可见区域内的 GridItem,当用户滚动时动态创建和回收子组件,内存占用大幅降低。API 24 对 LazyForEach 的回收策略做了进一步优化,回收延迟更小、帧率更稳定。
7.4 避免 GridItem 嵌套过深
每个 GridItem 内部的组件树深度会影响布局性能。对于简单的格子,应尽量扁平:
✅ 推荐(1 层嵌套):
GridItem → Column → Text + Text
❌ 避免(3+ 层嵌套):
GridItem → Column → Row → Column → Text
在九宫格示例中,每个 GridItem 只嵌套了一层 Column,这是最佳实践。
7.5 使用 ResourceColor 而非魔法字符串
虽然示例中直接使用了十六进制颜色字符串(如 '#FF6B81'),但在正式项目中,建议将颜色定义在资源文件中并通过 $r() 引用:
// resources/base/element/color.json
{
"color": [
{ "name": "grid_cell_1", "value": "#FF6B81" }
]
}
// 在代码中引用
.backgroundColor($r('app.color.grid_cell_1'))
这样做的好处:换肤支持、全局统一管理颜色、减小包体积。
八、扩展实战:从九宫格到更多布局
8.1 变成 4×4 宫格
只需修改一行代码:
.columnsTemplate('1fr 1fr 1fr 1fr') // 4 列
.rowsTemplate('1fr 1fr 1fr 1fr') // 4 行
同时将数据源增加到 16 项即可。这就是 Grid 的伸缩性——模板字符串描述布局结构,数据驱动内容。
8.2 非等宽九宫格(左侧窄导航 + 右侧宽内容)
.columnsTemplate('80vp 1fr 1fr')
.rowsTemplate('1fr 1fr 1fr')
第一列固定 80vp(适合做图标导航),后两列等分剩余空间(适合展示内容卡片)。
8.3 不规则网格(合并单元格)
ArkUI 的 GridItem 支持通过 columnStart、columnEnd、rowStart、rowEnd 属性实现跨行跨列:
GridItem() {
Text('跨列')
.width('100%').height('100%')
.backgroundColor('#FF6B81')
.textAlign(TextAlign.Center)
}
.columnStart(0)
.columnEnd(1) // 从第 0 列跨越到第 1 列
.rowStart(0)
.rowEnd(0)
这可以实现类似"网格中的大图 banner"效果,非常适合九宫格中突出显示某个特定项。
8.4 结合 Scroll 实现可滚动的网格
当 GridItem 数量超过一屏时,将 Grid 放入 Scroll 组件中:
Scroll() {
Grid() {
ForEach(this.cells, (item) => {
GridItem() { /* ... */ }
})
}
.columnsTemplate('1fr 1fr 1fr')
.rowsTemplate('1fr 1fr 1fr') // 固定 3 行,多余项自动换到 "下一屏"
}
.scrollable(ScrollDirection.Vertical)
API 24 中 Scroll + Grid 的联动效率得到提升,滚动过程中的布局计算不再阻塞主线程。
8.5 Grid 与动画结合
利用 API 24 新增的 gap 动画能力,可以实现网格间距的动态变化:
@State gapValue: number = 8;
Grid() {
// ...
}
.columnsGap(this.gapValue)
.rowsGap(this.gapValue)
// 通过点击按钮触发动画
Button('展开间距')
.onClick(() => {
animateTo({ duration: 300, curve: Curve.EaseInOut }, () => {
this.gapValue = 24; // 间距从 8vp 平滑过渡到 24vp
});
})
九、常见问题与排错
9.1 GridItem 不显示或显示异常
检查清单:
- Grid 是否设置了
columnsTemplate?(必须设置,否则 GridItem 不会排列) - GridItem 是否有明确的内容?(空的 GridItem 虽然存在但视觉不可见)
- 父容器是否有固定高度?(Grid 需要有确定的高度或通过约束计算出来)
ForEach的键值是否重复?(重复键值会导致渲染异常)
9.2 Grid 内容溢出或空白过多
原因:rowsTemplate 设置的行数与 GridItem 数量不匹配。
- 如果 GridItem 数量 > 行数 × 列数,Grid 会自动增加行,导致
rowsTemplate的部分设定失效。 - 如果 GridItem 数量 < 行数 × 列数,会留下空白格子。
解决方案:要么精确控制 GridItem 数量(如九宫格固定 9 项),要么使用 LazyForEach 适配动态数据。
9.3 各列宽度不一致
检查:columnsTemplate 字符串中的 token 是否被正确解析。
// ✅ 正确:空格分隔
.columnsTemplate('1fr 1fr 1fr')
// ❌ 错误:逗号分隔(ArkUI 不支持)
.columnsTemplate('1fr, 1fr, 1fr')
// ❌ 错误:多余空格
.columnsTemplate('1fr 1fr 1fr') // 双空格可能导致解析异常
9.4 性能问题:页面卡顿
诊断与优化:
| 问题 | 解决方案 |
|---|---|
| GridItem 中动画过多 | 减少不必要的动画,或使用 animateTo 替代逐帧状态更新 |
| 数据源过大 | 使用 LazyForEach 替代 ForEach |
| 嵌套过深 | 保持 GridItem 内部不超过 2 层容器嵌套 |
| 不必要的状态更新 | 仅在需要 UI 变化时修改 @State 变量,避免频繁赋值 |
十、总结
本文通过一个完整的九宫格示例,系统性地讲解了 HarmonyOS NEXT ArkTS 中 Grid 容器组件 的核心用法。
知识要点回顾:
- Grid 是二维网格布局容器,通过
columnsTemplate和rowsTemplate控制行列结构。 fr比例单位是构建响应式网格的关键,能够自动适配不同屏幕尺寸。ForEach+ 稳定键值实现高效列表渲染。- 圆角 + 渐变背景 + 阴影的"卡片三要素"提升视觉品质。
- 数据驱动 UI 是 ArkTS 声明式编程的核心思想。
从九宫格出发,Grid 的能力远不止于此——它可以是相册矩阵、商品网格、仪表盘面板、画板像素网格……掌握了 Grid,就掌握了鸿蒙原生布局体系中重要的一块拼图。
希望本文能为你的鸿蒙开发之旅提供切实的帮助。如果你在实践中有任何疑问或发现更酷的 Grid 用法,欢迎一起交流探讨。
本文配套完整源码位于 app014/entry/src/main/ets/pages/Index.ets,可直接在 DevEco Studio 中打开运行。
更多推荐




所有评论(0)