鸿蒙开发中Grid组件的全面解析与实战

本文同步发表于我的微信公众号,微信搜索 程语新视界 即可关注,每个工作日都有文章更新

一、Grid组件基础

1.1 Grid组件概述

Grid是鸿蒙ArkUI框架提供的网格布局容器,由"行"和"列"分割的单元格组成,通过指定子组件所在的单元格实现各种布局效果。Grid组件从API Version 7开始支持,后续版本不断增强了其功能。

核心特点

  • 支持自定义行列数和尺寸占比
  • 允许子组件跨越多行或多列
  • 提供水平和垂直两种布局方向
  • 支持滚动、懒加载等性能优化特性
  • 可与GridItem子组件配合实现复杂布局

1.2 Grid与GridItem关系

Grid的直接子组件必须是GridItem,这是网格布局的基本规则。GridItem用于定义网格中的单个项目,可以包含其他子组件。

重要说明

  • Grid子组件的索引值按顺序递增计算
  • if/else条件分支中,只有成立的分支会参与索引计算
  • ForEach/LazyForEach会展开所有子节点计算索引
  • visibility属性为Hidden或None时仍会计算索引 

二、Grid核心API与属性

2.1 布局控制API

2.1.1 行列模板(rowsTemplate/columnsTemplate)

通过设置行列模板确定网格的基本结构:

Grid() {
  // 子组件
}
.rowsTemplate('1fr 1fr 1fr') // 3行,每行高度相等
.columnsTemplate('1fr 2fr 1fr') // 3列,中间列宽度是两侧的2倍

高级用法

  • 使用repeat()函数简化重复模式
  • auto-fill/auto-fit实现自适应布局
// 自动填充列,最小列宽100vp
.columnsTemplate("repeat(auto-fit, 100vp)") 

// 按容器高度10%自动计算行数
.rowsTemplate("repeat(auto-fill, 10%)") 
2.1.2 行列间距(columnsGap/rowsGap)

控制网格行列之间的间距:

Grid()
  .columnsGap(10)  // 列间距10vp
  .rowsGap('5%')   // 行间距占容器高度的5%

注意:负值会被处理为0,优先级高于子组件边距

2.1.3 布局方向(layoutDirection)

控制子项的排列方向:

Grid()
  .layoutDirection(GridDirection.Row) // 默认,从左到右排列
  // 或 GridDirection.Column 从上到下排列

2.2 GridItem属性

GridItem用于定义网格中的单个项目,关键属性包括:

GridItem() {
  // 子组件
}
.rowStart(0)    // 起始行号
.rowEnd(1)      // 结束行号
.columnStart(0) // 起始列号
.columnEnd(1)   // 结束列号
.selectable(true) // 是否可被鼠标框选

注意事项

  • 行列号从0开始计数
  • 合理范围是0到总行数/列数-1
  • 只有设置了columnTemplate和rowTemplate的Grid中,这些属性才有效 

2.3 滚动控制API

2.3.1 滚动条设置
Grid()
  .scrollBar(BarState.Auto)    // 自动显示滚动条(API 10+默认)
  .scrollBarColor('#FFAABB')  // 自定义颜色
  .scrollBarWidth(6)          // 宽度6vp

支持的状态:

  • BarState.Off:隐藏滚动条
  • BarState.On:常显滚动条
  • BarState.Auto:滚动时显示 
2.3.2 滚动监听
Grid()
  .onScrollIndex((firstIndex: number) => {
    console.log('当前首项索引:', firstIndex)
  })

可用于实现分页加载等高级功能

2.4 性能优化API

2.4.1 懒加载缓存(cachedCount)
Grid()
  .cachedCount(3) // 上下各缓存3屏数据

仅对LazyForEach生效,平衡内存与流畅度

2.4.2 强制重建(forceRebuild)
GridItem()
  .forceRebuild(true) // 数据变更时重新计算布局

适用于动态增删或修改跨行跨列属性的场景

三、Grid高级特性

3.1 编辑模式(editMode)

启用拖拽排序功能(API 8+):

Grid()
  .editMode(true) // 允许用户拖拽GridItem调整位置

需配合onItemDragStart/onItemDragMove事件实现完整交互

3.2 多选模式(multiSelectable)

启用鼠标框选(API 8+):

Grid()
  .multiSelectable(true) // 配合onSelect事件获取选中项索引

适用于文件管理器等需要批量操作的场景

3.3 不规则布局(GridLayoutOptions)

处理跨行跨列的高级配置(API 10+):

Grid({ layoutOptions: {
  regularSize: [1, 1],          // 常规项占1行1列
  irregularIndexes: [0, 5],     // 指定不规则项的索引
  onGetIrregularSizeByIndex: (index) => {
    return (index === 0) ? [2, 1] : [1, 2] // 第0项跨2行,第5项跨2列
  }
}})

注意:垂直滚动Grid不支持跨多行,水平滚动不支持跨多列

3.4 响应式断点(GridRow/GridCol)

针对不同屏幕尺寸动态调整列数:

GridRow({
  columns: { xs: 2, sm: 4, md: 8, lg: 12 }, // 不同断点列数
  gutter: { x: 12, y: 8 },                  // 行列间距
  breakpoints: ['320vp', '520vp', '840vp']  // 断点阈值
}) {
  GridCol({ span: { xs: 1, lg: 2 } }) { /* 子项 */ }
}

实现自适应栅格系统,常用于仪表盘布局

四、Grid实战示例

4.1 基础网格布局

@Entry
@Component
struct BasicGridExample {
  build() {
    Grid() {
      GridItem() {
        Text('会议').fontSize(20)
      }.backgroundColor('#D4F2E7')

      GridItem() {
        Text('签到').fontSize(20)
      }.backgroundColor('#87CEFA')

      GridItem() {
        Text('投票').fontSize(20)
      }.backgroundColor('#FFF0F5')

      GridItem() {
        Text('打印').fontSize(20)
      }.backgroundColor('#E6E6FA')
    }
    .rowsTemplate('1fr 1fr')
    .columnsTemplate('1fr 1fr')
    .columnsGap(10)
    .rowsGap(15)
    .height('100%')
    .width('100%')
  }
}

4.2 可滚动网格布局

@Component
struct ScrollableGridExample {
  @State services: string[] = ['直播', '进口', '秒杀', '超市', '充值', '机票', '酒店', '电影', '理财', '美食']

  build() {
    Column({ space: 5 }) {
      Grid() {
        ForEach(this.services, (service: string) => {
          GridItem() {
            Text(service)
              .fontSize(16)
              .textAlign(TextAlign.Center)
              .width('100%')
              .height('100%')
          }
          .width('25%')
          .height(80)
          .backgroundColor('#FFFFFF')
        })
      }
      .rowsTemplate('1fr 1fr') // 只设置rowsTemplate,内容超出时可水平滚动
      .rowsGap(15)
      .height('80%')
      .width('100%')
    }
    .height('100%')
    .width('100%')
    .backgroundColor('#F1F3F5')
  }
}

4.3 不规则网格

// 不规则商品列表
@Entry
@Component
struct ECommerceGridExample {
  @State productList: Product[] = [
    { id: 1, type: 'banner' },
    { id: 2, type: 'normal' },
    { id: 3, type: 'normal' },
    { id: 4, type: 'normal' },
    { id: 5, type: 'promotion' },
    // 更多商品...
  ]

  build() {
    Grid({ layoutOptions: {
      regularSize: [1, 1],
      irregularIndexes: [0, 4],
      onGetIrregularSizeByIndex: (index) => 
        index === 0 ? [2, 2] : [1, 2]
    }}) {
      LazyForEach(this.productList, (item: Product, index: number) => {
        GridItem() {
          if (item.type === 'banner') {
            Image('banner.jpg')
              .objectFit(ImageFit.Cover)
          } else if (item.type === 'promotion') {
            Text('限时促销')
              .fontSize(18)
              .textAlign(TextAlign.Center)
          } else {
            Column() {
              Image('product.jpg')
                .width(80)
                .height(80)
              Text(`商品 ${item.id}`)
                .fontSize(14)
            }
          }
        }
        .backgroundColor('#FFF')
        .rowStart(index === 0 ? 1 : 2)
        .columnEnd(index === 4 ? 3 : 1)
      })
    }
    .columnsTemplate('1fr 1fr 1fr')
    .rowsTemplate('repeat(auto-fill, 200vp)')
    .columnsGap(8)
    .rowsGap(12)
    .scrollBar(BarState.Auto)
    .cachedCount(2)
    .height('100%')
    .width('100%')
  }
}

class Product {
  id: number;
  type: string;
}

效果说明

  • 首项为大图广告(跨2×2)
  • 第5项为横向促销栏(跨2列)
  • 支持懒加载与流畅滚动 

五、总结

5.1 性能优化建议

  1. 大数据集处理

    • 单页渲染超过50项时强制使用LazyForEach
    • 合理设置cachedCount(通常2-3)
    • 避免在GridItem中使用复杂计算 
  2. 渲染优化

    • 使用@Recycle装饰器复用组件
    • 简化GridItem内部结构
    • 避免频繁更新Grid布局属性 
  3. 内存管理

    • 对于动态内容,及时清理不可见项的资源
    • 监控Grid的内存使用情况
    • 在页面隐藏时释放非必要资源 

5.2 兼容性

  1. 版本差异

    • editMode、multiSelectable等特性需API 8+
    • GridLayoutOptions需要API 10+
    • 开发前需确认目标设备的API支持情况
  2. 布局限制

    • Grid直接子组件必须是GridItem
    • 复杂布局需在GridItem内部嵌套其他容器
    • 跨行跨列有方向限制(垂直滚动不支持跨多行等) 
  3. 调试技巧

    • 使用开发者工具的布局检查器
    • 开启Grid的边框显示辅助调试
    • 使用console.log输出布局计算的关键值

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值