harmony 鸿蒙网格布局

  • 2022-10-28
  • 浏览 (978)

网格布局

网格布局(GridLayout)是自适应布局中一种重要的布局,具备较强的页面均分能力,子组件占比控制能力。 通过Grid容器组件和子组件GridItem实现, Grid用于设置网格布局相关参数,GridItem定义子组件相关特征。优势如下:

  1. 容器组件尺寸发生变化时,所有子组件以及间距等比例调整,实现布局的自适应能力。
  2. 支持自定义网格布局行数和列数,以及每行每列尺寸占比。
  3. 支持设置网格布局中子组件的行列间距。
  4. 支持设置子组件横跨几行或者几列。

容器组件Grid设置

行列数量占比

通过Grid的组件的columnsTemplate和rowTemplate属性设置网格布局行列数量与尺寸占比。

下面以columnsTemplate为例,介绍该属性的设置,该属性值是一个由多个空格和’数字+fr’间隔拼接的字符串,fr的个数即网格布局的列数,fr前面的数值大小,用于计算该列在网格布局宽度上的占比,最终决定该列的宽度。

struct GridExample {
  @State Number: Array<string> = ['1', '2', '3', '4']

  build() {
    Column({ space: 5 }) {
      Grid() {
        ForEach(this.Number, (num: string) => {
          GridItem() {
            Text(`列${num}`)
              .fontSize(16)
              .textAlign(TextAlign.Center)
              .backgroundColor(0xd0d0d0)
              .width('100%')
              .height('100%')
              .borderRadius(5)
          }
        })
      }
      .columnsTemplate('1fr 1fr 1fr 1fr')
      .rowsTemplate('1fr')
      .columnsGap(10)
      .rowsGap(20)
      .width('90%')
      .backgroundColor(0xF0F0F0)
      .height(100)
    }.width('100%')
  }
}

定义了四个等分的列,每列宽度相等。

struct GridExample {
  @State Number: Array<string> = ['1', '2', '3', '4']

  build() {
    Column({ space: 5 }) {
      Grid() {
        ForEach(this.Number, (num: string) => {
          GridItem() {
            Text(`列${num}`)
              .fontSize(16)
              .textAlign(TextAlign.Center)
              .backgroundColor(0xd0d0d0)
              .width('100%')
              .height('100%')
              .borderRadius(5)
          }
        })
      }
      .columnsTemplate('1fr 2fr 3fr 4fr')
      .rowsTemplate('1fr')
      .columnsGap(10)
      .rowsGap(20)
      .width('90%')
      .backgroundColor(0xF0F0F0)
      .height(100)
    }.width('100%')
  }
}

定义了四列,每列宽度比值为1:2:3:4。

struct GridExample {
  @State Number: Array<string> = ['1', '2', '3']

  build() {
    Column({ space: 5 }) {
      Grid() {
        ForEach(this.Number, (num: string) => {
          GridItem() {
            Text(`列${num}`)
              .fontSize(16)
              .textAlign(TextAlign.Center)
              .backgroundColor(0xd0d0d0)
              .width('100%')
              .height('100%')
              .borderRadius(5)
          }
        })
      }
      .columnsTemplate('4fr 2fr 3fr')
      .rowsTemplate('1fr')
      .columnsGap(10)
      .rowsGap(20)
      .width('90%')
      .backgroundColor(0xF0F0F0)
      .height(100)
    }.width('100%')
  }
}

定义了三列,每列宽度比值为4:2:3。

效果如下:

排列方式

通过layoutDirection可以设置网格布局的主轴方向,决定子组件的排列方式。 可选值包括Row,RowReverse, Column, ColumnReverse四种情况。 效果如下:

行列间距

columnsGap用于设置网格子组件GridItem垂直方向的间距,rowsGap用于设置GridItem水平方向的间距。

Grid()
.columnsTemplate('1fr 1fr 1fr 1fr')
.columnsGap(10)
.rowsGap(20)

上图中,设置网格布局子组件间的垂直间距为20,水平间距为10。

网格子组件GridItem设置

设置子组件占的行列数

网格布局的行列标号从1开始,依次编号。

子组件横跨多行时,通过rowStart设置子组件起始行编号,rowEnd设置终点行编号。当rowStart值与rowEnd值相同时,子组件只占一个网格。示例如下:

Grid() {
    GridItem() {
      Text('5')
        .fontSize(16)
        .textAlign(TextAlign.Center)
        .textStyle()
    }.rowStart(2).rowEnd(3)  // 5子组件从第二行到第三行

    GridItem() {
      Text('4')
        .fontSize(16)
        .textAlign(TextAlign.Center)
        .textStyle()
    }.columnStart(4).columnEnd(5) // 4从第四列到第五列
  
    GridItem() {
      Text('6')
        .fontSize(16)
        .textAlign(TextAlign.Center)
        .textStyle()
    }.columnStart(2).columnEnd(4)  // 6从第二列到第四列

    GridItem() {
      Text('9')
        .fontSize(16)
        .textAlign(TextAlign.Center)
        .textStyle()
    }.columnStart(3).columnEnd(4)    // 从第三列到第四列
}
.columnsTemplate('1fr 1fr 1fr 1fr 1fr')
.rowsTemplate('1fr 1fr 1fr')
.columnsGap(10)
.rowsGap(20)
.width('90%')
.backgroundColor(0xF0F0F0)
.height('200vp')
.layoutDirection(GridDirection.Column)

场景示例

使用grid布局实现一个计算器的排布效果,代码如下:

@Entry
@Component
struct GridExample {
  @State Number: Array<string> = ['1', '2', '3', '+', '4', '5', '6', '-', '7', '8', '9', '*', '0', '.', '/']

  @Styles textStyle(){
    .backgroundColor(0xd0d0d0)
    .width('100%')
    .height('100%')
    .borderRadius(5)
  }

  build() {
    Column({ space: 5 }) {
      Grid() {
        GridItem() {
          Text('0')
            .fontSize(30)
            .textStyle()
        }.columnStart(1).columnEnd(4)

        GridItem() {
          Text('清空')
            .fontSize(16)
            .textAlign(TextAlign.Center)
            .textStyle()
        }.columnStart(1).columnEnd(2)

        GridItem() {
          Text('回退')
            .fontSize(16)
            .textAlign(TextAlign.Center)
            .textStyle()
        }.columnStart(3).columnEnd(4)

        ForEach(this.Number, (day: string) => {
          if (day === '0') {
            GridItem() {
              Text(day)
                .fontSize(16)
                .textAlign(TextAlign.Center)
                .textStyle()
            }.columnStart(1).columnEnd(2)
          } else {
            GridItem() {
              Text(day)
                .fontSize(16)
                .textAlign(TextAlign.Center)
                .textStyle()
            }
          }
        })
      }
      .columnsTemplate('1fr 1fr 1fr 1fr')
      .rowsTemplate('2fr 1fr 1fr 1fr 1fr 1fr')
      .columnsGap(10)
      .rowsGap(15)
      .width('90%')
      .backgroundColor(0xF0F0F0)
      .height('70%')
    }.width('100%').margin({ top: 5 })
  }
}

在大屏设备上展示效果如下:

在小屏设备下展示效果如下:

你可能感兴趣的鸿蒙文章

harmony 鸿蒙UI开发

harmony 鸿蒙方舟开发框架概述

harmony 鸿蒙文件组织

harmony 鸿蒙app.js

harmony 鸿蒙js标签配置

harmony 鸿蒙生命周期

harmony 鸿蒙多语言支持

harmony 鸿蒙资源限定与访问

harmony 鸿蒙CSS语法参考

harmony 鸿蒙HML语法参考

0  赞