HarMonyOS 鸿蒙系统使用 Grid构建网格

devtools/2025/1/11 14:26:48/

网格布局是由“行”和“列”分割的单元格所组成,通过指定“项目”所在的单元格做出各种各样的布局。网格布局具有较强的页面均分能力,子组件占比控制能力,是一种重要自适应布局,其使用场景有九宫格图片展示、日历、计算器等。

ArkUI提供了Grid容器组件和子组件GridItem,用于构建网格布局。Grid用于设置网格布局相关参数,GridItem定义子组件相关特征。Grid组件支持使用条件渲染、循环渲染、懒加载等方式生成子组件

布局与约束

Grid组件为网格容器,其中容器内各条目对应一个GridItem组件,如下图

设置排列方式

设置行列数量与占比

通过设置行列数量与尺寸占比可以确定网格布局的整体排列方式。Grid组件提供了rowsTemplate和columnsTemplate属性用于设置网格布局行列数量与尺寸占比。

rowsTemplate和columnsTemplate属性值是一个由多个空格和'数字+fr'间隔拼接的字符串,fr的个数即网格布局的行或列数,fr前面的数值大小,用于计算该行或列在网格布局宽度上的占比,最终决定该行或列宽度

如上图所示,构建的是一个三行三列的网格布局,其在垂直方向上分为三等份,每行占一份;在水平方向上分为四等份,第一列占一份,第二列占两份,第三列占一份。

只要将rowsTemplate的值为'1fr 1fr 1fr',同时将columnsTemplate的值为'1fr 2fr 1fr',即可实现上述网格布局

Grid() {...
}
.rowsTemplate('1fr 1fr 1fr')
.columnsTemplate('1fr 2fr 1fr')

说明:

当Grid组件设置了rowsTemplate或columnsTemplate时,Grid的layoutDirection、maxCount、minCount、cellLength属性不生效,属性说明可参考Grid-属性。

设置子组件所占行列数

除了大小相同的等比例网格布局,由不同大小的网格组成不均匀分布的网格布局场景在实际应用中十分常见,如下图所示。在Grid组件中,可以通过创建Grid时传入合适的GridLayoutOptions实现如图所示的单个网格横跨多行或多列的场景,其中,irregularIndexes和onGetIrregularSizeByIndex可对仅设置rowsTemplate或columnsTemplate的Grid使用;onGetRectByIndex可对同时设置rowsTemplate和columnsTemplate的Grid使用。

 

在网格中,可以通过onGetRectByIndex返回的[rowStart,columnStart,rowSpan,columnSpan]来实现跨行跨列布局,其中rowStart和columnStart属性表示指定当前元素起始行号和起始列号,rowSpan和columnSpan属性表示指定当前元素的占用行数和占用列数。

所以“0”按键横跨第一列和第二列,“=”按键横跨第五行和第六行,只要将“0”对应onGetRectByIndex的rowStart和columnStart设为5和0,rowSpan和columnSpan设为1和2,将“=”对应onGetRectByIndex的rowStart和columnStart设为4和3,rowSpan和columnSpan设为2和1即可。

layoutOptions: GridLayoutOptions = {regularSize: [1, 1],onGetRectByIndex: (index: number) => {if (index == key1) { // key1是“0”按键对应的indexreturn [5, 0, 1, 2]} else if (index == key2) { // key2是“=”按键对应的indexreturn [4, 3, 2, 1]}// ...// 这里需要根据具体布局返回其他item的位置}
}Grid(undefined, this.layoutOptions) {// ...
}
.columnsTemplate('1fr 1fr 1fr 1fr')
.rowsTemplate('2fr 1fr 1fr 1fr 1fr 1fr')

设置主轴方向

使用Grid构建网格布局时,若没有设置行列数量与占比,可以通过layoutDirection设置网格布局的主轴方向,决定子组件的排列方式。此时可以结合minCount和maxCount属性来约束主轴方向上的网格数量。

当前layoutDirection设置为Row时,先从左到右排列,排满一行再排下一行。当前layoutDirection设置为Column时,先从上到下排列,排满一列再排下一列,如上图所示。此时,将maxCount属性设为3,表示主轴方向上最大显示的网格单元数量为3。

Grid() {...
}
.maxCount(3)
.layoutDirection(GridDirection.Row)

在网格布局中显示数据

网格布局采用二维布局的方式组织其内部元素,如下图所示。

Grid组件可以通过二维布局的方式显示一组GridItem子组件。

Grid() {GridItem() {Text('会议')...}GridItem() {Text('签到')...}GridItem() {Text('投票')...}GridItem() {Text('打印')...}
}
.rowsTemplate('1fr 1fr')
.columnsTemplate('1fr 1fr')

对于内容结构相似的多个GridItem,通常更推荐使用ForEach语句中嵌套GridItem的形式,来减少重复代码。

@Entry
@Component
struct OfficeService {@State services: Array<string> = ['会议', '投票', '签到', '打印']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)}}
}

设置行列间距

在两个网格单元之间的网格横向间距称为行间距,网格纵向间距称为列间距,如下图所示。

通过Grid的rowsGap和columnsGap可以设置网格布局的行列间距。在图5所示的计算器中,行间距为15vp,列间距为10vp。

Grid() {...
}
.columnsGap(10)
.rowsGap(15)

构建可滚动的网格布局

可滚动的网格布局常用在文件管理、购物或视频列表等页面中,如下图所示。在设置Grid的行列数量与占比时,如果仅设置行、列数量与占比中的一个,即仅设置rowsTemplate或仅设置columnsTemplate属性,网格单元按照设置的方向排列,超出Grid显示区域后,Grid拥有可滚动能力。

 

如果设置的是columnsTemplate,Grid的滚动方向为垂直方向;如果设置的是rowsTemplate,Grid的滚动方向为水平方向。

如上图所示的横向可滚动网格布局,只要设置rowsTemplate属性的值且不设置columnsTemplate属性,当内容超出Grid组件宽度时,Grid可横向滚动进行内容展示。

@Entry
@Component
struct Shopping {@State services: Array<string> = ['直播', '进口']build() {Column({ space: 5 }) {Grid() {ForEach(this.services, (service: string, index) => {GridItem() {}.width('25%')}, (service:string):string => service)}.rowsTemplate('1fr 1fr') // 只设置rowsTemplate属性,当内容超出Grid区域时,可水平滚动。.rowsGap(15)}}
}

控制滚动位置

与新闻列表的返回顶部场景类似,控制滚动位置功能在网格布局中也很常用,例如下图所示日历的翻页功能。

 

Grid组件初始化时,可以绑定一个Scroller对象,用于进行滚动控制,例如通过Scroller对象的scrollPage方法进行翻页。

  1. private scroller: Scroller = new Scroller()

在日历页面中,用户在点击“下一页”按钮时,应用响应点击事件,通过指定scrollPage方法的参数next为true,滚动到下一页

Column({ space: 5 }) {Grid(this.scroller) {}.columnsTemplate('1fr 1fr 1fr 1fr 1fr 1fr 1fr')Row({space: 20}) {Button('上一页').onClick(() => {this.scroller.scrollPage({next: false})})Button('下一页').onClick(() => {this.scroller.scrollPage({next: true})})}
}

性能优化

与长列表的处理类似,循环渲染适用于数据量较小的布局场景,当构建具有大量网格项的可滚动网格布局时,推荐使用数据懒加载方式实现按需迭代加载数据,从而提升列表性能。

关于按需加载优化的具体实现可参考数据懒加载章节中的示例。

当使用懒加载方式渲染网格时,为了更好的滚动体验,减少滑动时出现白块,Grid组件中也可通过cachedCount属性设置GridItem的预加载数量,只在懒加载LazyForEach中生效。

设置预加载数量后,会在Grid显示区域前后各缓存cachedCount*列数个GridItem,超出显示和缓存范围的GridItem会被释放。

Grid() {LazyForEach(this.dataSource, () => {GridItem() {}})
}
.cachedCount(3)

 


http://www.ppmy.cn/devtools/149628.html

相关文章

解决nginx多层代理后应用部署后访问发现css、js、图片等样式加载失败

一般是采用前后端分离部署方式&#xff0c;被上一层ng代理后&#xff0c;通过域名访问报错&#xff0c;例如&#xff1a;sqx.com.cn/应用代理路径。 修改nginx配置&#xff0c;配置前端页面的路径&#xff1a; location / {proxy_pass http://前端页面所在服务器的IP:PORT;pro…

RT-Thread Studio中的静态线程是什么

RT-Thread Studio中的静态线程是RT-Thread实时操作系统中线程的一种创建方式。以下是对RT-Thread Studio中静态线程的详细解释&#xff1a; 一、定义与特点 定义&#xff1a; 静态线程是在编译时就确定了线程的数量和属性&#xff0c;将线程的控制块和堆栈空间预分配好&#x…

js装饰器模式

装饰器模式是一种结构型设计模式&#xff0c;它允许你在不改变对象结构的情况下&#xff0c;动态地给对象添加新的行为或职责。 装饰器模式通过创建一个装饰器类&#xff0c;来包装原始对象&#xff0c;并在不改变原始对象的基础上&#xff0c;为其添加新的功能。装饰器类和原始…

【Linux】gawk编辑器

一、基本介绍 相较于sed编辑器来说&#xff0c;gawk提供了一种编程语言&#xff0c;而不仅仅是编辑器命令。 在gawk编程语言中&#xff0c;可以实现以下操作&#xff1a; 定义变量来保存数据&#xff1b;使用算术和字符串运算符来处理数据&#xff1b;使用结构化编程语法&…

自动化巡检系统如何提高运维效率?

一、自动化巡检系统简介 &#xff08;一&#xff09;定义与基本原理 自动化巡检系统是一种借助先进的信息技术&#xff0c;旨在对各类系统进行高效、精准监测的智能化工具。它主要依靠预设的脚本、专业的监测工具以及相关的软件模块&#xff0c;按照既定的规则和流程&#xff0…

Wireshark编译手册(Windows)

以下是对 Wireshark 官方文档中“Windows 平台的设置和构建说明”部分的翻译和总结&#xff1a; 2.2. Windows 平台 本节提供了在 Windows 上进行 Wireshark 开发的快速设置指南&#xff0c;包含推荐的配置。 2.2.1. 使用 Microsoft Visual Studio 注意&#xff1a;除非您非…

Jenkins内修改allure报告名称

背景&#xff1a; 最近使用Jenkins搭建自动化测试环境时&#xff0c;使用Jenkins的allure插件生成的报告&#xff0c;一直显示默认ALLURE REPORT&#xff0c;想自定义成与项目关联的名称&#xff0c;如图所示&#xff0c;很明显自定义名称显得高大上些&#xff0c;之前…

Python 模块 Uvicorn 实战指南

文章目录 1. 介绍和安装1.1 介绍1.2 安装 2. 创建基础应用2.1 简单的 HTTP 应用2.2 添加日志 3. 实现高级功能3.1 支持 WebSocket3.2 优化运行性能 4. Nginx 配置反向代理4.1 安装与配置 Nginx4.2 启用 SSL 支持4.3 性能优化建议 5. 常见问题与解决方案5.1 高并发问题5.2 WebSo…