HarmonyOS5 便捷生活类——Grid单元格合并布局(点主页有系列文章)

加入下方官方班级,得鸿蒙礼盒

一起拿鸿蒙礼盒,戳我戳我!!

本期活动时间:2025年8月1日-12月31日


问题现象

在开发过程中,Grid布局是构建页面结构的强大工具。特别是在复杂界面设计中,开发者常需利用Grid布局实现单元格的灵活合并,以确保界面元素的精准对齐和响应式调整,从而提升用户体验。

效果预览

背景知识

  • 创建网格 (Grid/GridItem):网格布局是由“行”和“列”分割的单元格所组成,通过指定“项目”所在的单元格做出各种各样的布局。网格布局具有较强的页面均分能力和子组件占比控制能力,是一种重要自适应布局,其使用场景有九宫格图片展示、日历、计算器等。
  • GridItem:网格容器中单项内容容器,具有若干设置容器的属性。
  • 设置子组件所占行列数:在Grid组件中,可以通过创建Grid时传入合适的GridLayoutOptions实现如图所示的单个网格横跨多行或多列的场景。

解决方案

方案一:通过GridItem的行列跨度属性合并单元格。

  1. 适用场景。

    场景

    举例说明

    简单跨行/跨列

    适用于需要手动控制少量单元格合并的场景,例如:

    1. 表格标题栏跨多列(如合并首行前3列)。
    2. 九宫格首项占据整行(如电商首页Banner)。
    3. 日历中的周末日期合并(如周六、周日跨列显示)。

    固定布局需求

    当布局结构固定且无需频繁调整时,直接设置行列号更直观,例如:

    1. 固定导航栏按钮排列。
    2. 商品分类标签的固定组合。
  2. 实现方式。

    从背景知识中可知,若要实现问题现象中的预期效果,可以对GridItem进行设置。GridItem有属性如下:

    GridItem的属性

    说明

    rowStart

    设置当前元素起始行号。

    rowEnd

    设置当前元素终点行号。

    columnStart

    设置当前元素起始列号。

    columnEnd

    设置当前元素终点列号。

    对于预期效果图进行分析:

    这是一个五行四列的网格布局,其中编号1、2、3的网格占了整行(合并列),它们的元素起始列号为0,元素终点列号为3,如果设置了rowStart/rowEnd/columnStart/columnEnd,GridItem会占据指定的行数(rowEnd-rowStart+1)或列数(columnEnd-columnStart+1)。

    编号9的网格元素起始列号为1,元素终点列号为3,但若将其列号设置的与1、2、3号网格一样,则9号会和8号产生位置冲突。在设置行列号布局时,若该区域位置存在GridItem布局,则会产生避让,因此9号按照1、2、3号网格进行相同设置,同样能实现预期效果。

     
    interface listItem {
    type: string
    value: string
    }
    
    @Entry
    @Component
    struct Index {
    @State text: string = 'drag'
    @State titleIndex: number = 0
    @State numbers: listItem[] =
    [{ type: 'title', value: '1' }, { type: 'title', value: '2' }, { type: 'title', value: '3' },
    { type: 'item', value: '4' }, { type: 'item', value: '5' }, { type: 'item', value: '6' },
    { type: 'item', value: '7' }, { type: 'item', value: '8' }, { type: 'title', value: '9' },]
    
    build() {
    Column({ space: 4 }) {
    Grid() {
    ForEach(this.numbers, (item: listItem) => {
    GridItem() {
    Text(item.value)
    .fontSize(16)
    .backgroundColor(0x0A59F7)
    .width('100%')
    .height('100%')
    .textAlign(TextAlign.Center)
    }
    .columnStart(item.type == 'title' ? 0 : undefined)
    .columnEnd(item.type == 'title' ? 3 : undefined)
    .height('100%')
    .width('100%')
    }, (item: listItem, index: number) => item.value)
    }
    .columnsTemplate('1fr 1fr 1fr 1fr')
    .rowsTemplate('1fr 1fr 1fr 1fr 1fr')
    .columnsGap(10)
    .rowsGap(10)
    .width('90%')
    .backgroundColor(0xFAEEE0)
    .height(300)
    .animation({
    duration: 300,
    curve: Curve.Smooth
    })
    }
    .width('100%')
    .margin({ top: 5 })
    }
    }

方案二:通过layoutOptions配置不规则布局。

  1. 适用场景。

    场景

    举例说明

    复杂不规则布局场景

    适用于需要稍微复杂的计算单元格尺寸或位置的场景。例如:

    1. 计算器按键布局(如“0”键跨2列,“=”键跨2行)。
    2. 促销广告栏横向跨多列(如“买一送一”横跨3列)。
    3. 可滚动的跨行跨列场景

    频繁合并单元格场景

    当网格项数量较多时,layoutOptions通过预计算布局减少渲染开销,避免因频繁操作行列号导致的性能问题。

  2. 实现方式。

    制作不均匀的网格布局也可以通过onGetRectByIndex返回的rowStart、columnStart、rowSpan、columnSpan来实现跨行跨列布局。

    onGetRectByIndex的属性

    说明

    rowStart

    当前元素起始行号。

    columnStart

    当前元素起始列号。

    rowSpan

    指定当前元素的占用行数。

    columnSpan

    指定当前元素的占用列数。

    对于预期效果图进行分析:

    为了实现预期效果,可以对网格进行起始位置以及占用列数的设置,如编号1号的网格起始行号为0,起始列号也为0,占用行数为1,占用列数为4;编号9号的网格起始行号为4,起始列号为1,占用行数为1,占用列数为3。其余网格依次推理,在此不再赘述。更多示例详见:固定行列Grid

     
    layoutOptions: GridLayoutOptions = {
    regularSize: [1, 1],
    onGetRectByIndex: (index: number) => {
    if (index == 0) {
    return [0, 0, 1, 4]
    } else if (index == 8) {
    return [1, 4, 1, 3]
    } else {
    // 布局其他item的位置
    // ...
    }
    }
    }
    
    Grid(undefined, this.layoutOptions) {
    // ...
    }
    .columnsTemplate('1fr 1fr 1fr 1fr')
    .rowsTemplate('1fr 1fr 1fr 1fr 1fr')

总结

在HarmonyOS的Grid布局中,合并单元格的两种方法(行列跨度属性和layoutOptions配置)各有其适用场景和优缺点。以下是详细对比及场景建议:

维度

行列跨度属性(rowStart/rowEnd等)

layoutOptions配置

实现方式

手动指定单元格的起始和结束行列号。

通过配置对象动态定义常规项与不规则项的尺寸和位置。

代码复杂度

简单直观,适合少量单元格操作。

需理解配置逻辑,适合复杂布局。

动态响应

需手动更新行列号,动态场景维护成本高。

支持响应式断点,自动适配屏幕变化。

性能表现

大量单元格时可能影响渲染效率。

通过预计算优化布局,性能更优。

适用布局类型

规则网格中的局部合并(如标题栏、首图)。

高度不规则布局(如计算器按键、促销广告位)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值