《频道选择》二、GridItem使用指南

HarmonyOS ArkTS GridItem 网格子项组件使用指南

前言

在 HarmonyOS ArkUI 中,GridItem是 Grid 网格容器的子组件,用于定义网格中每个单元格的内容与特征。GridItem 不仅能承载任意 UI 组件,还支持跨行、跨列、偏移等高级布局能力。本文将全面解析 GridItem 的核心属性与使用技巧,并通过实战示例帮助开发者灵活运用。

本文基于 HarmonyOS API 23+,使用 ArkTS 语言开发。


效果

一、GridItem 组件概述

GridItem 是 Grid 容器的直接子组件,用于定义网格单元的内容。Grid 与 GridItem 的关系类似于 HTML 中<table><td>的关系。

基本使用规则:

  • GridItem 只能作为 Grid 的直接子组件使用
  • 每个 GridItem 对应网格中的一个单元格
  • GridItem 内部可以放置任意 UI 组件
Grid(){GridItem(){// 任意UI组件Text('单元格1')}GridItem(){Text('单元格2')}}

二、核心属性详解

2.1 跨列 — gridSpan

gridSpan用于设置 GridItem 在列方向上跨越的单元格数量。

属性类型说明
gridSpannumber该单元格在列方向上跨越的单元格个数,默认值为 1
Grid(){// 普通单元格,占1列GridItem(){Text('普通')}// 跨2列的单元格GridItem(){Text('跨2列')}.gridSpan(2)}.columnsTemplate('1fr 1fr 1fr')

典型场景:频道选择中的"推荐"频道横跨两列,广告位横跨整行。

2.2 跨行 — gridRowSpan

gridRowSpan用于设置 GridItem 在行方向上跨越的单元格数量。

属性类型说明
gridRowSpannumber该单元格在行方向上跨越的单元格个数,默认值为 1
Grid(){// 横跨2行的单元格GridItem(){Text('跨2行')}.gridRowSpan(2)GridItem(){Text('A')}GridItem(){Text('B')}GridItem(){Text('C')}}.columnsTemplate('1fr 1fr').rowsTemplate('80 80 80')

2.3 列偏移 — gridOffset

gridOffset用于设置 GridItem 在列方向上的偏移量,即在该 GridItem 之前预留的空单元格数量。

属性类型说明
gridOffsetnumber在列方向上偏移的单元格个数,默认值为 0
Grid(){GridItem(){Text('偏移2列')}.gridOffset(2)// 前面空出2个单元格位置GridItem(){Text('下一个')}}.columnsTemplate('1fr 1fr 1fr 1fr')

2.4 强制换行 — forceNewLine

forceNewLine用于强制将该 GridItem 放置在下一行的起始位置。

属性类型说明
forceNewLineboolean是否强制换行,默认值为 false
Grid(){GridItem(){Text('第1行-1')}GridItem(){Text('第1行-2')}GridItem(){Text('第2行起始')}.forceNewLine(true)// 强制到下一行GridItem(){Text('第2行-2')}}.columnsTemplate('1fr 1fr 1fr')

2.5 组合使用

GridItem 的布局属性可以自由组合,实现复杂的网格布局:

Grid(){// 左上角大卡片:跨2列2行GridItem(){Image($r('app.media.banner'))}.gridSpan(2).gridRowSpan(2)// 右侧两个小卡片GridItem(){Text('资讯')}GridItem(){Text('视频')}// 底部横跨整行GridItem(){Text('热门推荐')}.gridSpan(3).forceNewLine(true)}.columnsTemplate('1fr 1fr 1fr').rowsTemplate('100 100 60').columnsGap(8).rowsGap(8)

三、GridItem 与渲染控制

3.1 ForEach 循环渲染

最常用的方式是通过ForEach动态生成 GridItem:

@Statetags:string[]=['科技','娱乐','体育','财经','教育','健康']Grid(){ForEach(this.tags,(tag:string)=>{GridItem(){Text(tag).fontSize(14).padding({left:12,right:12}).height(36).borderRadius(18).backgroundColor('#F1F3F5').textAlign(TextAlign.Center)}},(tag:string)=>tag)}.columnsTemplate('1fr 1fr 1fr').columnsGap(10).rowsGap(12)

3.2 条件渲染

在 ForEach 中结合if实现条件渲染:

Grid(){ForEach(this.items,(item:ItemType)=>{if(item.visible){GridItem(){Text(item.name)}}})}

3.3 LazyForEach 懒加载

数据量大时使用LazyForEach提升性能:

Grid(){LazyForEach(this.dataSource,(item:ItemType,index:number)=>{GridItem(){Column(){Image(item.imageUrl)Text(item.title)}}})}.cachedCount(2)// 预加载数量

四、完整实战示例:仪表盘布局

以下示例展示如何利用 GridItem 的跨行跨列能力,构建一个仪表盘风格的布局。

4.1 示例效果

  • 顶部大卡片跨2列,展示核心数据
  • 中间4个等大小数据卡片
  • 底部横跨整行的汇总信息栏
  • 总计3列 × 3行的网格布局

4.2 完整代码

// DashboardGrid.ets@Entry@Componentstruct DashboardGrid{@Statemetrics:MetricItem[]=[{title:'今日访问',value:'12,580',color:'#4ECDC4'},{title:'新增用户',value:'326',color:'#45B7D1'},{title:'活跃用户',value:'8,942',color:'#96CEB4'},{title:'转化率',value:'24.6%',color:'#FF6B6B'}]build(){Column({space:16}){Text('数据仪表盘').fontSize(22).fontWeight(FontWeight.Bold).width('100%').padding({left:16})Grid(){// 核心数据卡片:跨2列GridItem(){Column({space:8}){Text('总收入').fontSize(16).fontColor(Color.White)Text('¥ 128,650').fontSize(28).fontWeight(FontWeight.Bold).fontColor(Color.White)Text('较昨日 +12.5%').fontSize(13).fontColor('#CCFFFFFF')}.width('100%').height('100%').justifyContent(FlexAlign.Center).backgroundColor('#6C5CE7').borderRadius(16)}.gridSpan(2)// 右侧通知卡片GridItem(){Column({space:6}){Text('📢').fontSize(24)Text('3条新消息').fontSize(13).fontColor('#333333')}.width('100%').height('100%').justifyContent(FlexAlign.Center).backgroundColor('#FFF3E0').borderRadius(16)}// 中间4个指标卡片ForEach(this.metrics,(item:MetricItem)=>{GridItem(){Column({space:4}){Text(item.title).fontSize(12).fontColor('#666666')Text(item.value).fontSize(18).fontWeight(FontWeight.Bold).fontColor(item.color)}.width('100%').height('100%').justifyContent(FlexAlign.Center).backgroundColor('#F8F9FA').borderRadius(12)}},(item:MetricItem)=>item.title)// 底部汇总栏:跨3列,强制换行GridItem(){Row(){Text('📊 本周数据汇总').fontSize(14).fontWeight(FontWeight.Medium)Blank()Text('查看详情 →').fontSize(13).fontColor('#6C5CE7')}.width('100%').height('100%').padding({left:16,right:16}).backgroundColor('#EDE7F6').borderRadius(12)}.gridSpan(3).forceNewLine(true)}.columnsTemplate('1fr 1fr 1fr').rowsTemplate('120 100 50').columnsGap(12).rowsGap(12).padding({left:16,right:16}).width('100%')}.width('100%').height('100%').padding({top:20})}}interfaceMetricItem{title:stringvalue:stringcolor:string}

五、关键知识点总结

属性作用默认值
gridSpan列方向跨单元格数1
gridRowSpan行方向跨单元格数1
gridOffset列方向偏移单元格数0
forceNewLine强制换到下一行起始false

使用建议:

  1. gridSpan不能超过 Grid 的总列数
  2. 使用gridRowSpan时需确保 Grid 有明确的rowsTemplate,否则可能导致布局异常
  3. gridOffset+gridSpan的总和不能超过当前行的剩余列数
  4. 大数据量场景优先使用LazyForEach搭配cachedCount

六、常见问题

Q1: gridSpan 设置为大于列数的值会怎样?

GridItem 会被限制在 Grid 的列数范围内,超出的部分不生效。

Q2: gridRowSpan 跨行后其他 GridItem 如何排列?

被跨行占用的单元格位置会被跳过,后续 GridItem 自动填充到下一个可用位置。

Q3: forceNewLine 在最后一列使用时效果?

该 GridItem 会被放置在下一行的起始位置,等同于正常换行。


七、参考资料

  • GridItem 官方 API 文档
  • Grid 官方 API 文档
  • HarmonyOS 开发者文档中心