HarmonyOS鸿蒙Next中如何使用Grid实现动态交错网格布局?

HarmonyOS鸿蒙Next中如何使用Grid实现动态交错网格布局?

如何使用 GridcolumnsTemplatelayoutDirection 实现动态交错网格布局?

3 回复

实现效果

cke_11518.png

实现思路

1、定义列模板,设置 columnsTemplate: ‘1fr 1fr’,将容器分为均等的两列。

交错的逻辑核心在于控制单元格的列跨度。

数据模型设计:

定义一个 GridItemModel 类,包含一个 type 字段,用于标识该数据是“大图”还是“小图”。

动态列跨度控制:

在 ForEach 渲染 GridItem 时,根据数据的 type 动态绑定 .columnStart 和 .columnEnd 属性。

逻辑:

大图项:columnStart(0) 到 columnEnd(1),横跨两列。

小图项:不设置(默认跨度为 1),各占一列。

通过数据源中 [‘Large’, ‘Small’, ‘Small’] 的循环模式,自然形成错落感。

应用场景

1、在生成照片墙照片,突出显示某张精彩大片的场景。

2、商品推荐列表,偶发展示宽幅海报等

完整代码

// 定义网格项的数据模型
class GridItemModel {
  id: string;
  type: 'large' | 'small'; 
  bgColor: string;        
  height: number;         

  constructor(id: string, type: 'large' | 'small', bgColor: string, height: number) {
    this.id = id;
    this.type = type;
    this.bgColor = bgColor;
    this.height = height;
  }
}

@Entry
@Component
struct StaggeredGridDemo {
  // 生成“一大两小”循环的数据源
  private dataList: GridItemModel[] = [
    new GridItemModel('1', 'large', '#FFCDD2', 240),
    new GridItemModel('2', 'small', '#C8E6C9', 110),
    new GridItemModel('3', 'small', '#BBDEFB', 110),

    new GridItemModel('4', 'large', '#FFE0B2', 220),
    new GridItemModel('5', 'small', '#D1C4E9', 100),
    new GridItemModel('6', 'small', '#B2DFDB', 100),

    new GridItemModel('7', 'large', '#F8BBD0', 260),
    new GridItemModel('8', 'small', '#CFD8DC', 120),
    new GridItemModel('9', 'small', '#E1BEE7', 120),
  ];

  build() {
    Column() {
      Text("动态交错网格布局")
        .fontSize(24)
        .fontWeight(FontWeight.Bold)
        .margin({ top: 40, bottom: 20 })
      Grid() {
        ForEach(this.dataList, (item: GridItemModel) => {
          GridItem() {
            Column() {
              Text(item.type === 'large' ? 'Large Item' : 'Small')
                .fontSize(18)
                .fontColor(Color.White)
                .margin({ top: 10 })
              Text(item.id)
                .fontSize(12)
                .fontColor(Color.White)
            }
            .width('100%')
            .height(item.height)
            .backgroundColor(item.bgColor)
            .borderRadius(8)
            .justifyContent(FlexAlign.Start)
            .alignItems(HorizontalAlign.Start)
            .padding({ left: 10 })
          }
          // ==========================================
          // 根据类型动态设置列跨度
          // ==========================================
          // Grid 的列索引是从 0 开始的。
          // columnsTemplate: '1fr 1fr' 表示有 2 列,索引分别是 0 和 1
          .columnStart(item.type === 'large' ? 0 : (item.id === '2' || item.id === '5' || item.id === '8' ? 0 : 1))
          .columnEnd(item.type === 'large' ? 1 : (item.id === '2' || item.id === '5' || item.id === '8' ? 0 : 1))
          // 1. 如果是 'large',从第 0 列跨越到第 1 列 (占满整行)。
          // 2. 如果是 'small',需要根据奇偶性决定放在左边还是右边。
          //    这里为了演示,硬编码了 ID 判断,实际开发中可以增加 index 索传来计算。
          //    计算逻辑:index % 3 === 1 时放左边,=== 2 时放右边。
        }, (item: GridItemModel) => item.id)
      }
      .columnsTemplate('1fr 1fr') // 关键:将网格分为均等的两列
      .rowsGap(10)                // 行间距
      .columnsGap(10)             // 列间距
      .width('90%')
      .height('100%')
      .layoutWeight(1)
      .backgroundColor('#F5F5F5')
    }
    .width('100%')
    .height('100%')
    .backgroundColor('#FFFFFF')
  }
}

更多关于HarmonyOS鸿蒙Next中如何使用Grid实现动态交错网格布局?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


在HarmonyOS Next中,使用Grid组件实现动态交错网格布局,可通过设置rowsTemplate和columnsTemplate定义网格结构。利用GridItem组件填充每个网格单元,结合ForEach动态渲染数据源。通过条件判断或数据模型中的特定属性,控制GridItem的rowStart、rowEnd、columnStart和columnEnd属性,实现项目跨越多行或多列的交错效果。布局的“动态”性由数据源驱动,数据变化时ForEach自动更新GridItem。

在HarmonyOS Next中,使用Grid组件实现动态交错网格布局,核心在于灵活配置columnsTemplate属性并配合layoutDirection来控制子组件的排列流向。

1. 核心属性配置

  • columnsTemplate: 这是实现交错布局的关键。你需要定义一个重复的列模板。例如,'1fr 1fr'表示两列等宽网格。为了实现“交错”效果,你通常需要设置一个多列的网格结构(如两列或三列),这样项目就可以在不同列中错开排列。
  • layoutDirection: 将其设置为GridDirection.Row(默认值),确保子组件按行优先的顺序填充网格。这是交错布局的标准流向。

2. 实现动态交错

动态交错意味着子组件的高度或跨度可能不同,从而在视觉上形成错落有致的布局。这主要通过为GridItem设置rowStartrowEnd(或columnStartcolumnEnd)属性来实现。

  • 关键步骤
    1. 定义一个多列的columnsTemplate(例如两列:'1fr 1fr')。
    2. 在遍历数据生成GridItem时,根据数据项的索引或特定属性,动态计算并设置其rowStartrowEnd值。
    3. 通过控制每个项目所占的行数(rowEnd - rowStart),使相邻项目在垂直方向上不对齐,从而实现交错效果。

3. 示例代码片段

以下是一个简化的ArkTS示例,展示如何实现一个两列交错的动态布局:

@Entry
@Component
struct DynamicStaggeredGrid {
  // 假设的数据源,其中包含项目的高度信息(用于计算行跨度)
  @State dataItems: Array<{ id: number, rowSpan: number }> = [
    { id: 1, rowSpan: 2 }, { id: 2, rowSpan: 1 },
    { id: 3, rowSpan: 1 }, { id: 4, rowSpan: 2 },
    // ... 更多数据
  ];

  build() {
    Grid() {
      ForEach(this.dataItems, (item: { id: number, rowSpan: number }) => {
        GridItem() {
          // 你的项目内容组件,高度由样式或内容决定
          Text(`Item ${item.id}`)
            .width('100%')
            .height(100 * item.rowSpan) // 示例:根据rowSpan设置不同高度
            .backgroundColor(Color.Blue)
            .textAlign(TextAlign.Center)
        }
        // 动态计算并设置网格行位置,实现交错的关键
        .rowStart(this.calculateRowStart(item.id))
        .rowEnd(this.calculateRowStart(item.id) + item.rowSpan)
      })
    }
    // 定义两列等宽网格
    .columnsTemplate('1fr 1fr')
    .layoutDirection(GridDirection.Row)
    .width('100%')
    .height('100%')
    .backgroundColor(Color.White)
  }

  // 一个简单的计算函数,用于根据项目ID和之前项目的rowSpan累加计算起始行
  // 注意:这是一个基础示例,实际逻辑需根据你的具体布局算法调整
  calculateRowStart(index: number): number {
    // 此处应实现你的具体行起始位置计算逻辑。
    // 例如,可以遍历之前所有项目,累加它们的rowSpan。
    // 这里返回一个固定值仅作演示。
    let start = 0;
    for (let i = 0; i < index; i++) {
      // 假设this.dataItems在方法内可访问,实际可能需要将数据作为参数传入
      // start += this.dataItems[i].rowSpan;
    }
    return start; // 实际开发中需要完善此计算逻辑
  }
}

4. 重要说明

  • 上述示例中的calculateRowStart函数需要你根据实际业务逻辑进行完善。核心是跟踪当前已占用的行数,以确定下一个项目的起始行。对于复杂的交错布局,计算逻辑可能更精细。
  • 你也可以通过设置columnStartcolumnEnd来实现水平方向上的交错,原理类似。
  • 确保GridItem的总行跨度(rowEnd - rowStart)与GridrowsTemplate(如果定义)或动态计算的行布局相匹配,以避免布局冲突。

通过组合使用columnsTemplate定义网格结构,并结合GridItem的动态rowStart/rowEnd(或columnStart/columnEnd)设置,你可以有效地在HarmonyOS Next中创建出各种动态交错网格布局。

回到顶部