鸿蒙应用开发UI基础第三十六节:Grid网格布局二维自适应宫格与不规则布局方案

张开发
2026/4/17 6:13:46 15 分钟阅读

分享文章

鸿蒙应用开发UI基础第三十六节:Grid网格布局二维自适应宫格与不规则布局方案
【学习目标】掌握Grid/GridItem组件的核心架构、父子组件约束规则理解二维网格布局的核心逻辑吃透Grid组件六大核心配置行列模板、排列方向、行列间距、滚动控制、不规则布局、性能优化的完整用法掌握不规则网格的实现方案搞定跨行跨列布局的核心配置与开发技巧通过示例实现固定功能九宫格、计算器不规则布局、可滚动商品网格一、本节工程目录GridLayoutDemo/ ├── entry/ │ └── src/ │ └── main/ │ ├── ets/ │ │ ├── entryability/ │ │ │ └── EntryAbility.ets // 应用入口工程自动生成 │ │ ├── pages/ │ │ │ ├── Index.ets // 导航首页3个示例入口 │ │ │ ├── GridBaseDemo.ets // 示例1基础九宫格布局 │ │ │ ├── GridIrregularDemo.ets // 示例2不规则网格布局 │ │ │ └── GridGoodsDemo.ets // 示例3可滚动商品网格实战 │ │ └── utils/ // 工具类目录 │ ├── resources/ // 应用资源目录 │ │ ├── base/element/ │ │ └── base/media/ │ └── module.json5 // 模块配置文件 └── build-profile.json5 // 工程配置文件二、网格布局核心基础2.1 什么是网格布局网格布局是鸿蒙官方提供的二维自适应布局组件以「Grid容器GridItem子项」为核心架构Grid作为父容器定义整体的行、列规则将页面切分成若干个规整的单元格GridItem作为子容器必须作为Grid的直接子组件使用用于承载每个单元格的具体内容它可以同时控制水平、垂直两个方向的布局规则既能实现等分的规整宫格也能实现跨行跨列的不规则布局天然具备自适应能力。核心规则Grid的直接子组件只能是GridItemGridItem必须嵌套在Grid容器内两者单独使用均无布局效果。2.2 网格布局核心适配逻辑Grid容器通过行列规则确定整体网格的单元格数量、尺寸占比GridItem按规则依次填充单元格可自定义跨行跨列的占用范围容器尺寸发生变化时所有单元格与间距会按占比等比例缩放无需手动适配仅设置行/列其中一项规则时超出容器显示区域的内容Grid自动支持对应方向的滚动三、Grid容器配置详解Grid是网格布局的核心所有全局规则均在Grid容器上配置下面我们逐一拆解每个核心配置的用法、规则。3.1 核心构造函数语法Grid(scroller?:Scroller,layoutOptions?:GridLayoutOptions)scroller可选项绑定滚动控制器用于控制网格的滚动位置、翻页、回到顶部等操作layoutOptions可选项用于配置不规则网格的跨行跨列规则3.2 核心配置一行列模板通过rowsTemplate和columnsTemplate两个属性定义网格的行列数量、每行每列的尺寸占比是网格布局最核心的配置。3.2.1 属性语法规则属性值为**「数字fr」通过空格分隔的字符串**核心规则如下fr是网格布局的专属占比单位fr的个数 对应方向的行列数量例rowsTemplate(1fr 1fr 1fr)代表垂直方向分为3行例columnsTemplate(1fr 1fr 1fr 1fr)代表水平方向分为4列fr前的数字为占比权重数字越大对应行/列在父容器中的占比越高例columnsTemplate(1fr 2fr 1fr)代表3列宽度占比为1:2:1相同权重下所有行/列会均分父容器对应方向的尺寸例rowsTemplate(1fr 1fr 1fr)代表3行每行高度均分容器总高度3.2.2 布局约束与滚动规则这是开发中最容易踩坑的点必须严格遵守配置场景布局效果滚动能力同时设置rowsTemplate columnsTemplate仅展示固定行列数的内容超出部分不展示不可滚动仅设置rowsTemplate行数固定列数自适应内容水平排列超出容器宽度可横向滚动仅设置columnsTemplate列数固定行数自适应内容垂直排列超出容器高度可纵向滚动两者都不设置行列数由布局方向、单元格尺寸共同决定超出内容不展示不可滚动3.3 核心配置二主轴排列方向通过layoutDirection属性设置网格的主轴排列方向仅在未同时设置rowsTemplate和columnsTemplate时生效。枚举值布局效果GridDirection.Row默认值主轴为水平方向先从左到右排满一行再换行从上到下排列GridDirection.Column主轴为垂直方向先从上到下排满一列再换列从左到右排列GridDirection.RowReverse水平反向排列从右到左、从上到下GridDirection.ColumnReverse垂直反向排列从下到上、从左到右配套约束属性maxCount主轴方向上最大的单元格数量minCount主轴方向上最小的单元格数量cellLength主轴方向上单个单元格的固定尺寸3.4 核心配置三行列间距通过rowsGap和columnsGap分别设置网格的行间距与列间距避免单元格紧贴在一起提升布局美观度。rowsGap设置行与行之间的垂直间距单位vpcolumnsGap设置列与列之间的水平间距单位vp3.5 核心配置四滚动控制Grid组件可通过绑定Scroller控制器实现滚动位置控制、翻页、回到顶部等操作仅在Grid具备滚动能力时生效仅设置单个行列模板。核心使用步骤初始化Scroller滚动控制器将控制器绑定到Grid构造函数通过控制器的API实现各类滚动操作核心滚动APIAPI功能说明scrollPage({next: boolean})滚动到上一页/下一页next为true向下/向右翻页false向上/向左翻页scrollEdge(Edge.Top/Edge.Bottom)滚动到容器顶部/底部scrollEdge(Edge.Start/Edge.End)滚动到容器最左侧/最右侧currentOffset()获取当前滚动的偏移量3.6 核心配置五不规则网格布局通过layoutOptions配置实现单个GridItem跨行跨列的不规则布局适用于计算器、日历、个性化宫格等场景。核心配置语法// 不规则布局配置privatelayoutOptions:GridLayoutOptions{regularSize:[1,1],// 常规单元格默认占用[行数,列数]// 自定义每个单元格的位置与占用范围onGetRectByIndex:(index:number){// 返回值格式[起始行号, 起始列号, 占用行数, 占用列数]// 注意行列号从0开始编号}}// 绑定到Grid构造函数Grid(undefined,this.layoutOptions){// GridItem子项}四、GridItem子组件详解GridItem是网格布局的子项容器负责承载每个单元格的具体内容核心使用规则如下强制父子约束Grid的直接子组件只能是GridItemGridItem内部可嵌套任意布局组件Row/Column/Image/Text等尺寸自适应GridItem的宽高默认跟随Grid的行列模板自动适配无需手动设置固定宽高避免破坏网格规则跨行跨列配置单个GridItem的跨行跨列规则通过Grid的layoutOptions统一配置无需在GridItem上单独设置交互支持GridItem支持点击、触摸、长按等通用事件可实现单元格的各类交互逻辑样式自定义GridItem内部可自由设置背景、圆角、阴影等样式不影响网格整体布局规则五、演示示例5.1 实战一基础功能九宫格对应知识点行列模板、行列间距、基础GridItem用法实现APP首页常见的功能入口九宫格可直接复制运行。interfaceIMenu{name:string,icon:string}Entry Component struct GridBaseDemo{// 功能入口数据privatemenuList:IMenu[][{name:首页,icon:},{name:分类,icon:},{name:发现,icon:},{name:购物车,icon:},{name:我的,icon:},{name:设置,icon:⚙️},{name:消息,icon:},{name:客服,icon:},{name:关于,icon:ℹ️}]build(){Column(){Text(功能入口九宫格).fontSize(22).fontWeight(FontWeight.Bold).margin({bottom:20})Grid(){ForEach(this.menuList,(item:IMenu){GridItem(){Column({space:10}){Text(item.icon).fontSize(32)Text(item.name).fontSize(14).fontColor(#333333)}.width(100%).height(100%).justifyContent(FlexAlign.Center).backgroundColor($r(sys.color.comp_background_list_card)).borderRadius(12).shadow({radius:4,color:#00000010})}},(item:IMenu)item.name)}.rowsTemplate(1fr 1fr 1fr).columnsTemplate(1fr 1fr 1fr).rowsGap(16).columnsGap(16).width(90%).layoutWeight(1)}.width(100%).height(360).backgroundColor(#F5F5F5).padding(20)}}运行效果5.2 实战二计算器不规则布局对应知识点不规则网格配置、跨行跨列实现完整还原计算器按键布局可直接复制运行。Entry Component struct GridIrregularDemo{State currentKey:string0// 计算器按键数据privatekeyList:string[][AC,/-,%,÷,7,8,9,×,4,5,6,-,1,2,3,,0,.,];privatescroller:ScrollernewScroller()// 不规则布局配置privatelayoutOptions:GridLayoutOptions{regularSize:[1,1],onGetRectByIndex:(index:number){// 按键0第5行第0列占1行2列if(index16){return[4,0,1,2];}// 其余按键默认1行1列return[Math.floor(index/4),index%4,1,1];}}build(){Column(){// 计算器显示区域Column(){Text(this.currentKey).fontSize(48).fontColor($r(sys.color.comp_background_list_card)).fontWeight(FontWeight.Regular).maxLines(1).textOverflow({overflow:TextOverflow.Ellipsis}).width(90%).textAlign(TextAlign.End)}.justifyContent(FlexAlign.End).alignItems(HorizontalAlign.End).width(90%).height(35%).padding(20)// 计算器按键网格Grid(this.scroller,this.layoutOptions){ForEach(this.keyList,(key:string,index:number){GridItem(){Button({buttonStyle:ButtonStyleMode.NORMAL,type:index16?ButtonType.Capsule:ButtonType.Circle}){Text(key).fontSize(28).fontColor(index4?#000000:#FFFFFF).fontWeight(index%43||index18?FontWeight.Bold:FontWeight.Medium).textAlign(TextAlign.Center)}.backgroundColor(index4?#A5A5A5:index%43||index18?#FF9F0A:#333333).width(100%).height(100%)}.onClick((){this.currentKeykey})},(key:string)key)}.rowsTemplate(1fr 1fr 1fr 1fr 1fr 1fr).columnsTemplate(1fr 1fr 1fr 1fr).columnsGap(12).rowsGap(12).width(90%).layoutWeight(1)}.width(100%).height(100%).backgroundColor(#121212)}}运行效果5.3 实战三可滚动商品网格列表对应知识点垂直滚动网格、懒加载性能优化、滚动控制集成Search搜索组件实现电商APP常见的商品网格列表可直接复制运行。// 商品数据模型interfaceGoodsItem{id:string;name:string;price:number;cover:string;}Entry Component struct GridGoodsDemo{State goodsList:GoodsItem[][];privatescroller:ScrollernewScroller();// 初始化商品数据aboutToAppear(){for(leti0;i60;i){this.goodsList.push({id:i.toString(),name:鸿蒙旗舰商品${i1},price:99i*10,cover:});}}build(){Stack(){Column(){this.navgationBarBuilder()// 商品网格列表Grid(this.scroller){ForEach(// 可以使用LazyForEachthis.goodsList,(item:GoodsItem){GridItem(){this.GoodsItemCard(item);}.onClick((){console.info(点击商品${item.name});})},(item:GoodsItem)item.id// 唯一标识)}.columnsTemplate(1fr 1fr).columnsGap(12).rowsGap(12).padding(12).width(100%).layoutWeight(1).backgroundColor(#F5F5F5)}.width(100%).height(100%)// 回到顶部悬浮按钮Button(回到顶部).width(100).height(40).fontSize(14).backgroundColor(Color.White).fontColor(Color.Black).borderRadius(20).shadow({radius:4,color:#00000010}).position({right:20,bottom:30}).onClick((){this.scroller.scrollTo({xOffset:0,yOffset:0});})}.width(100%).height(100%).backgroundColor(#F5F5F5);}BuildernavgationBarBuilder(){// 顶部导航栏Row({space:10}){Text(商品列表).fontSize(20).fontWeight(FontWeight.Bold).fontColor(Color.Black)Search({placeholder:搜索商品}).height(36).layoutWeight(1).padding({left:15}).backgroundColor(#F5F5F5).borderRadius(18).placeholderColor(#999999).textAlign(TextAlign.Start).border({width:0.5,color:#EEEEEE,radius:18});}.width(100%).height(50).justifyContent(FlexAlign.Center).backgroundColor(Color.White).zIndex(10).padding({left:15,right:15});}// 商品卡片组件BuilderGoodsItemCard(item:GoodsItem){Column({space:8}){// 商品封面Row(){Text(item.cover).fontSize(40)}.width(100%).aspectRatio(1).backgroundColor(#E0E0E0).borderRadius(12).justifyContent(FlexAlign.Center).alignItems(VerticalAlign.Center);// 商品名称Text(item.name).fontSize(14).fontColor(#333333).maxLines(2).textOverflow({overflow:TextOverflow.Ellipsis}).width(100%);// 商品价格Text(¥${item.price.toFixed(2)}).fontSize(16).fontColor(#FF3B30).fontWeight(FontWeight.Bold).width(100%);}.width(100%).padding(10).backgroundColor(Color.White).borderRadius(12).shadow({radius:2,color:#00000008});}}运行效果六、最佳实践与高频避坑指南行列模板规范固定宫格场景同时设置rowsTemplate和columnsTemplate保证布局可控可滚动列表场景仅设置其中一个开启对应方向滚动间距规范行列间距推荐使用8-16vp保证视觉一致性避免间距过大或过小导致布局失衡性能规范数据量超过50条的可滚动网格推荐LazyForEach懒加载不推荐使用ForEach全量渲染预加载规范cachedCount推荐设置3-5平衡滚动体验与内存开销避免设置过大导致内存占用过高布局规范GridItem内部使用百分比宽高或自适应布局禁止设置固定宽高破坏网格的自适应能力七、内容总结核心架构网格布局采用「Grid容器GridItem子项」的父子架构Grid负责全局行列规则GridItem负责单个单元格内容承载核心配置通过rowsTemplate/columnsTemplate定义行列规则通过layoutOptions实现不规则布局通过Scroller实现滚动控制核心能力同时管控水平垂直两个方向的布局天然具备自适应能力支持规整宫格与不规则跨行跨列布局核心场景固定功能九宫格、计算器、日历、商品网格、视频宫格等二维布局场景性能优化大数据场景必须使用LazyForEach懒加载配合cachedCount预加载提升滚动体验八、代码仓库示例工程GridLayoutDemo仓库地址https://gitee.com/HarmonyOS-UI-Basics/harmony-os-ui-basics.git九、下节预告下一节我们将正式学习瀑布流布局核心组件 WaterFlow彻底掌握不等高自适应滚动布局开发掌握 WaterFlow/FlowItem 核心架构与自动填充规则实现双列不等高瀑布流、无限滚动、下拉刷新、触底预加载掌握滑动窗口模式、组件复用、懒加载等瀑布流专属性能优化方案

更多文章