网格布局是创建响应式和结构化用户界面的强大工具。通过将界面划分为由行和列组成的单元格,网格可以精确控制组件的分布和对齐。这使得它们成为各种应用程序(例如图库、日历和计算器)的理想选择。
在 HarmonyOS 中,ArkUI 提供了用于构建网格布局的Grid
容器和GridItem
组件。Grid
组件用于定义网格的结构,而GridItem
组件指定每个单元格内的内容。HarmonyOS 网格支持条件渲染、循环渲染和延迟加载等高级功能,以高效处理大型数据集。
布局和约束
组件Grid
充当网格容器,每个网格项由一个GridItem
组件表示。它们之间的关系如下:
Grid
└── GridItem
└── Component
注意: Grid
组件必须只能包含GridItem
作为子组件的组件。
网格布局本质上是二维的,提供垂直和水平排列功能。它们可以适应容器尺寸的变化,确保响应式设计。根据设置,您可以创建各种网格布局,例如下面显示的布局:
Grid Layout Variants
└── Evenly Distributed Grid
└── Asymmetrical Grid
└── Scrollable Grid
关键行为:
- 如果同时设置了
Grid
组件的宽度和高度,它将占据指定的尺寸。 - 如果未设置尺寸,则将
Grid
适应其父容器的大小。
组件Grid
的布局根据行和列的配置可以分为三种类型:
- **固定行和列:**显示固定数量的元素而不滚动。
- **动态行或列:**根据设置的行数或列数,以可滚动的布局显示元素。
- **灵活布局:**根据方向和网格大小布局元素,如果不适合则隐藏多余的元素。
配置行和列
网格布局的整体结构通过设置行数和列数以及它们的尺寸比例来定义。Grid
组件使用rowsTemplate
和columnsTemplate
属性来实现此目的。
例子:
Grid() {
...
}
.rowsTemplate('1fr 1fr 1fr') // Three equally sized rows
.columnsTemplate('1fr 2fr 1fr') // Three columns, with the middle column twice the size of the others
**注意:**设置rowsTemplate
或时,其他属性(如、和)将被忽略。columnsTemplate``layoutDirection``maxCount``minCount
管理跨越和不对称
在实际应用中,网格通常包含跨多行或多列的项目,例如计算器键或日历日期。这可以通过配置来实现GridLayoutOptions
。
例子:
layoutOptions: GridLayoutOptions = {
regularSize: [1, 1],
onGetRectByIndex: (index: number) => {
if (index == key1) { // Key "0"
return [5, 0, 1, 2]
} else if (index == key2) { // Key "="
return [4, 3, 2, 1]
}
}
}
Grid(undefined, this.layoutOptions) {
// Grid content here
}
.columnsTemplate('1fr 1fr 1fr 1fr')
.rowsTemplate('2fr 1fr 1fr 1fr 1fr 1fr')
此代码将“0”键跨越两列,将“=”键跨越两行。
设置布局方向
如果您未设置行和列模板,则可以使用来layoutDirection
确定项目在网格内的排列方式。
例子:
Grid() {
...
}
.maxCount(3)
.layoutDirection(GridDirection.Row) // Items will fill rows first
行为:
- **行方向:**项目按从左到右的顺序排列,并根据需要换行到下一行。
- **列方向:**项目按从上到下的顺序排列,并换行到下一列。
以网格布局显示数据
网格布局可以有效地显示一组项目,尤其是当内容相似时,例如服务列表。
例子:
@Entry
@Component
struct OfficeService {
@State services: Array<string> = ['Meeting', 'Check-in', 'Vote', 'Print']
build() {
Column() {
Grid() {
ForEach(this.services, (service:string) => {
GridItem() {
Text(service)
}
}, (service:string):string => service)
}
.rowsTemplate(('1fr 1fr') as string)
.columnsTemplate(('1fr 1fr') as string)
}
}
}
管理网格项之间的间距
rowsGap
可以使用和属性来控制行和列之间的空间columnsGap
。
例子:
Grid() {
...
}
.columnsGap(10) // 10px gap between columns
.rowsGap(15) // 15px gap between rows
创建可滚动的网格
可滚动网格对于显示大量内容(例如在文件管理器或购物应用中)至关重要。当仅设置rowsTemplate
或之一时columnsTemplate
,网格将变为可滚动的。
例子:
@Entry
@Component
struct Shopping {
@State services: Array<string> = ['Live', 'Imports']
build() {
Column({ space: 5 }) {
Grid() {
ForEach(this.services, (service: string, index) => {
GridItem() {
}
.width('25%')
}, (service:string):string => service)
}
.rowsTemplate('1fr 1fr') // Scrolls horizontally if content exceeds width
.rowsGap(15)
}
}
}
控制滚动位置
网格中的滚动控制对于用户体验至关重要,例如翻阅日历中的页面。
例子:
private scroller: Scroller = new Scroller()
Column({ space: 5 }) {
Grid(this.scroller) {
}
.columnsTemplate('1fr 1fr 1fr 1fr 1fr 1fr 1fr')
Row({space: 20}) {
Button('Previous Page')
.onClick(() => {
this.scroller.scrollPage({
next: false
})
})
Button('Next Page')
.onClick(() => {
this.scroller.scrollPage({
next: true
})
})
}
}
使用延迟加载进行性能优化
对于大型数据集,建议使用延迟加载来优化性能。您可以使用该cachedCount
属性控制网格项的预加载,以确保平滑滚动。
例子:
Grid() {
LazyForEach(this.dataSource, () => {
GridItem() {
}
})
}
.cachedCount(3) // Preload 3 items before and after the visible area
**注意:**增加cachedCount
可改善用户体验,但可能会增加 CPU 和内存的使用率。
结论
HarmonyOSGrid
组件是一款多功能工具,可用于创建复杂且响应迅速的网格布局。无论您是构建简单的网格还是复杂的可滚动界面,了解和利用各种属性和选项都可以让您创建高效且具有视觉吸引力的设计。