HarmonyOS鸿蒙Next中如何使用Grid实现动态交错网格布局?
HarmonyOS鸿蒙Next中如何使用Grid实现动态交错网格布局?
如何使用 Grid 的 columnsTemplate 与 layoutDirection 实现动态交错网格布局?
实现效果

实现思路
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设置rowStart和rowEnd(或columnStart和columnEnd)属性来实现。
- 关键步骤:
- 定义一个多列的
columnsTemplate(例如两列:'1fr 1fr')。 - 在遍历数据生成
GridItem时,根据数据项的索引或特定属性,动态计算并设置其rowStart和rowEnd值。 - 通过控制每个项目所占的行数(
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函数需要你根据实际业务逻辑进行完善。核心是跟踪当前已占用的行数,以确定下一个项目的起始行。对于复杂的交错布局,计算逻辑可能更精细。 - 你也可以通过设置
columnStart和columnEnd来实现水平方向上的交错,原理类似。 - 确保
GridItem的总行跨度(rowEnd - rowStart)与Grid的rowsTemplate(如果定义)或动态计算的行布局相匹配,以避免布局冲突。
通过组合使用columnsTemplate定义网格结构,并结合GridItem的动态rowStart/rowEnd(或columnStart/columnEnd)设置,你可以有效地在HarmonyOS Next中创建出各种动态交错网格布局。

