电商网站 建社区,wordpress 代码文章,东莞朝阳网站建设,做品牌推广应该怎么做鸿蒙学习实战之路-Grid 网格布局组件全攻略 最近在写鸿蒙页面时#xff0c;发现好多布局用传统的 Flex 和 Column/Row 组合起来特别麻烦#xff0c;尤其是那种网格状的布局#xff0c;比如淘宝首页的功能入口、小米有品的分类导航#xff0c;简直想抠脑壳 o(╯□╰)o 今天这…鸿蒙学习实战之路-Grid 网格布局组件全攻略最近在写鸿蒙页面时发现好多布局用传统的 Flex 和 Column/Row 组合起来特别麻烦尤其是那种网格状的布局比如淘宝首页的功能入口、小米有品的分类导航简直想抠脑壳 o(╯□╰)o今天这篇我就手把手带你搞定 GridGridItem 网格布局组件从基础到进阶保证你看完就能上手一、Grid 是什么Grid 组件就像是一个布局神器专门用来创建网格状的 UI 界面。简单来说就是把屏幕分成若干行和列然后把内容放在这些格子里。举个例子你看淘宝首页的这些功能入口是不是整整齐齐的网格用 Grid 实现简直不要太轻松 西兰花小贴士Grid 和 Flex 的区别Flex 是一维布局要么行要么列Grid 是二维布局同时控制行和列。就像搭积木Flex 是一列一列摆Grid 是一块一块铺二、Grid 基础用法2.1 固定行列布局最基础的 Grid 用法就是创建固定行列数的网格比如 3 行 2 列的布局。组件结构Grid() { GridItem() { // 展示的内容放在这里 Text(1) .fontColor(Color.White) .fontSize(30) } .backgroundColor(Color.Blue) GridItem() { Text(2) .fontColor(Color.White) .fontSize(30) } .backgroundColor(Color.Blue) }西兰花警告Grid 的子组件必须是 GridItem不能直接放其他组件GridItem 只能有一个子组件要放多个内容记得用容器包起来Grid 如果不设置宽高会默认继承父组件的尺寸。基础属性名称参数类型描述columnsTemplatestring设置列数和宽度比例如’1fr 1fr 2fr’表示 3 列宽度比例 1:1:2rowsTemplatestring设置行数和高度比例如’1fr 1fr’表示 2 行高度各占一半columnsGapLength设置列间距默认 0rowsGapLength设置行间距默认 0实战练习我们来创建一个 3 列 2 行的网格列宽比例 1:2:1行高各占一半带 10px 间距Entry Component struct GridBasicExample { build() { Column() { Text(固定行列布局) .fontSize(20) .fontWeight(900) .padding(10) Grid() { // 第1行 GridItem() { Text(1) .fontColor(Color.White) .fontSize(30) } .backgroundColor(Color.Blue) GridItem() { Text(2) .fontColor(Color.White) .fontSize(30) } .backgroundColor(Color.Blue) GridItem() { Text(3) .fontColor(Color.White) .fontSize(30) } .backgroundColor(Color.Blue) // 第2行 GridItem() { Text(4) .fontColor(Color.White) .fontSize(30) } .backgroundColor(Color.Blue) GridItem() { Text(5) .fontColor(Color.White) .fontSize(30) } .backgroundColor(Color.Blue) GridItem() { Text(6) .fontColor(Color.White) .fontSize(30) } .backgroundColor(Color.Blue) } .border({ width: 1 }) .columnsTemplate(1fr 2fr 1fr) .rowsTemplate(1fr 1fr) .width(100%) .height(360) .columnsGap(10) .rowsGap(10) } .width(100%) .height(100%) } }三、实战案例淘宝二楼效果现在咱们来整个实战案例实现淘宝二楼的功能入口布局注代码中的图片可以自行替换成 其他图片保证代码逻辑正确即可效果展示需求分析实现 5x5 的网格布局每个网格包含图标和文字整体使用渐变色背景参考代码interface TaoBaoItemContent { title: string icon: ResourceStr // $r(图片名)返回的是Resource类型ResourceStr是联合类型Resource|string } Entry Component struct TaoBaoSecondFloor { contentList: TaoBaoItemContent[] [ { title: 淘金币, icon: $r(app.media.ic_taobao_01) }, { title: 一起摇现金, icon: $r(app.media.ic_taobao_02) }, { title: 闲鱼, icon: $r(app.media.ic_taobao_03) }, { title: 中通快递, icon: $r(app.media.ic_taobao_04) }, { title: 芭芭农场, icon: $r(app.media.ic_taobao_05) }, { title: 淘宝珍库, icon: $r(app.media.ic_taobao_06) }, { title: 阿里拍卖, icon: $r(app.media.ic_taobao_07) }, { title: 阿里药房, icon: $r(app.media.ic_taobao_08) }, { title: 小黑盒, icon: $r(app.media.ic_taobao_09) }, { title: 菜鸟, icon: $r(app.media.ic_taobao_10) }, { title: U先试用, icon: $r(app.media.ic_taobao_11) }, { title: 有好价, icon: $r(app.media.ic_taobao_12) }, { title: 极有家, icon: $r(app.media.ic_taobao_13) }, { title: 天猫榜单, icon: $r(app.media.ic_taobao_14) }, { title: 天天特卖, icon: $r(app.media.ic_taobao_15) }, { title: 每日好店, icon: $r(app.media.ic_taobao_16) }, { title: 全球购, icon: $r(app.media.ic_taobao_17) }, { title: 我的爱车, icon: $r(app.media.ic_taobao_18) }, { title: 造点新货, icon: $r(app.media.ic_taobao_19) }, { title: 首单优惠, icon: $r(app.media.ic_taobao_20) }, { title: 潮Woo, icon: $r(app.media.ic_taobao_21) }, { title: 亲宝贝, icon: $r(app.media.ic_taobao_22) }, { title: 领券中心, icon: $r(app.media.ic_taobao_23) }, { title: 天猫奢品, icon: $r(app.media.ic_taobao_24) }, { title: iFashion, icon: $r(app.media.ic_taobao_25) } ] build() { Column() { Column() { // 顶部返回区域 this.backBuilder() // 搜索框区域 this.searchBuilder() // Grid区域 this.gridBuilder() } } .width(100%) .height(100%) .linearGradient({ colors: [ [#271b41, 0], [#481736, 1], ] }) } Builder backBuilder() { // 顶部返回区域 Row() { Image($r(app.media.ic_taobao_back)) .fillColor(Color.White) .width(30) Text(最近使用) .fontSize(20) .fontColor(Color.White) } .width(100%) .padding({ top: 40 }) } Builder searchBuilder() { // 搜索框区域 Stack() { Text() .width(100%) .height(40) .backgroundColor(Color.White) .opacity(.3) .borderRadius(20) Row({ space: 10 }) { Image($r(app.media.ic_taobao_search)) .width(25) .fillColor(Color.White) Text(搜索) .fontSize(15) .fontColor(Color.White) } .padding({ left: 10 }) .width(100%) } .padding(10) } Builder gridBuilder() { // Grid区域 Grid() { ForEach(this.contentList, (item: TaoBaoItemContent, index: number) { GridItem() { Column({ space: 10 }) { Image(item.icon) .width(40) Text(item.title) .fontColor(Color.White) .fontSize(14) } } }) } .columnsTemplate(1fr 1fr 1fr 1fr 1fr) .rowsTemplate(1fr 1fr 1fr 1fr 1fr) .width(100%) .height(360) } } 西兰花小贴士这里用了Builder 装饰器把布局拆分成几个小模块代码看起来更清晰这就像是把一个大蛋糕切成小块吃起来更方便~四、合并行列不规则网格有时候咱们需要实现不规则的网格布局比如有的格子跨两行有的跨两列。这时候就需要用到 GridItem 的合并属性了合并属性名称参数类型描述rowStartnumber指定当前元素起始行号rowEndnumber指定当前元素终点行号columnStartnumber指定当前元素起始列号columnEndnumber指定当前元素终点列号实战练习实现不规则网格我们来把一个 4 列 3 行的规则网格改造成不规则布局Entry Component struct GridMergeExample { // 快速生成12个元素的数组 nums: number[] Array.from({ length: 12 }) build() { Column() { Text(合并行列) .fontSize(20) .fontWeight(900) .padding(10) Grid() { ForEach(this.nums, (item: number, index: number) { if (index 2) { GridItem() { Text(index ) .fontColor(Color.White) .fontSize(30) } .backgroundColor(#9dc3e6) .columnStart(3) .columnEnd(4) } else if (index 3) { GridItem() { Text(index ) .fontColor(Color.White) .fontSize(30) } .backgroundColor(#9dc3e6) .rowStart(2) .rowEnd(3) } else { GridItem() { Text(index ) .fontColor(Color.White) .fontSize(30) } .backgroundColor(#9dc3e6) } }) } .columnsTemplate(1fr 1fr 1fr 1fr) .rowsTemplate(1fr 1fr 1fr) .width(100%) .height(260) .rowsGap(10) .columnsGap(10) .padding(10) } .width(100%) .height(100%) } } 西兰花小贴士快速生成指定长度的数组小技巧Array.from({ length: 12 })想要多长就把 length 设为多少五、滚动网格在实际开发中经常会遇到内容超出屏幕的情况这时候就需要用到滚动网格了。设置滚动方向水平滚动设置rowsTemplateGrid 的滚动方向为水平方向垂直滚动设置columnsTemplateGrid 的滚动方向为垂直方向实战练习垂直滚动网格// 为Text扩展属性newExtend Extend(Text) function newExtend() { .width(100%) .height(100%) .fontSize(30) .fontColor(Color.White) .textAlign(TextAlign.Center) } Entry Component struct GridScrollExample { // 生成30个元素的数组 list: string[] Array.from({ length: 30 }) build() { Column() { Text(垂直滚动网格) .fontSize(20) .fontWeight(900) .padding(10) Grid() { ForEach(this.list, (item: string, index) { GridItem() { Text((index 1).toString()) .newExtend() } .padding(5) .backgroundColor(#0094ff) .height(30%) // 竖向滚动-通过height设置高度 }) } .columnsTemplate(1fr 1fr 1fr) // 竖向滚动 固定列数 .rowsGap(10) .columnsGap(10) .width(100%) .height(300) .border({ width: 1 }) .padding(5) } .width(100%) .height(100%) } }六、实战案例小米有品横向滚动导航咱们来实现小米有品的横向滚动导航效果注代码中的图片可以自行替换成 其他图片保证代码逻辑正确即可效果展示参考代码interface NavItem { title: string icon: ResourceStr // 联合属性 Resource | string } Entry Component struct XiaomiYoupinNav { // 数据 navList: NavItem[] [ { title: 上新精选, icon: $r(app.media.ic_xiaomi_nav_01) }, { title: 智能家电, icon: $r(app.media.ic_xiaomi_nav_02) }, { title: 小米众筹, icon: $r(app.media.ic_xiaomi_nav_03) }, { title: 有品会员, icon: $r(app.media.ic_xiaomi_nav_04) }, { title: 有品秒杀, icon: $r(app.media.ic_xiaomi_nav_05) }, { title: 原产地, icon: $r(app.media.ic_xiaomi_nav_06) }, { title: 生活优选, icon: $r(app.media.ic_xiaomi_nav_07) }, { title: 手机, icon: $r(app.media.ic_xiaomi_nav_08) }, { title: 小米自营, icon: $r(app.media.ic_xiaomi_nav_09) }, { title: 茅台酒饮, icon: $r(app.media.ic_xiaomi_nav_10) }, { title: 鞋服饰品, icon: $r(app.media.ic_xiaomi_nav_11) }, { title: 家纺餐厨, icon: $r(app.media.ic_xiaomi_nav_12) }, { title: 食品生鲜, icon: $r(app.media.ic_xiaomi_nav_13) }, { title: 好惠买, icon: $r(app.media.ic_xiaomi_nav_14) }, { title: 家具家装, icon: $r(app.media.ic_xiaomi_nav_15) }, { title: 健康养生, icon: $r(app.media.ic_xiaomi_nav_16) }, { title: 有品海购, icon: $r(app.media.ic_xiaomi_nav_17) }, { title: 个护清洁, icon: $r(app.media.ic_xiaomi_nav_18) }, { title: 户外运动, icon: $r(app.media.ic_xiaomi_nav_19) }, { title: 3C数码, icon: $r(app.media.ic_xiaomi_nav_20) } ] build() { Column() { Text(小米有品) .fontSize(20) .fontWeight(900) .padding(10) Grid() { ForEach(this.navList, (item: NavItem) { GridItem() { Column() { Image(item.icon) .width(80%) Text(item.title) .fontSize(12) } .height(100%) } .width(20%) }) } .rowsTemplate(1fr 1fr) .height(160) .width(100%) .backgroundColor(Color.White) .borderRadius(5) .padding({ bottom: 10 }) .scrollBar(BarState.Off) // 关闭滚动条 } .width(100%) .height(100%) .padding(10) .backgroundColor(#f5f5f5) } }七、代码控制滚动有时候我们需要通过代码来控制 Grid 的滚动比如实现上一页/下一页的按钮。这时候就需要用到 Scroller 控制器了核心步骤创建 Scroller 对象设置给 Grid调用 Scroller 对象的 scrollPage 方法参考代码Entry Component struct GridControllerExample { nums: number[] Array.from({ length: 200 }) // 控制器对象不是状态属性不需要添加任何修饰符 scroller: Scroller new Scroller() build() { Column() { Text(控制器-代码控制滚动) .fontSize(20) .fontWeight(900) .padding(10) Grid(this.scroller) { ForEach(this.nums, (item: number, index: number) { GridItem() { Text(index 1 ) .fontColor(Color.White) .fontSize(20) .width(100%) .height(100%) .textAlign(TextAlign.Center) } .backgroundColor(#0094ff) .width(25%) }) } .padding(10) .height(450) .rowsGap(10) .columnsGap(10) .rowsTemplate(1fr 1fr 1fr 1fr) Row() { Button(上一页) .width(100) .onClick(() { // 上一页 this.scroller.scrollPage({ next: false }) }) Button(下一页) .width(100) .onClick(() { // 下一页 this.scroller.scrollPage({ next: true }) }) } .width(100%) .justifyContent(FlexAlign.SpaceAround) } } }八、总结GridGridItem 组件真的是鸿蒙布局中的瑞士军刀无论是规则的网格布局还是复杂的不规则布局都能轻松应对核心知识点回顾基础用法固定行列布局使用 columnsTemplate 和 rowsTemplate 设置行列数和比例合并行列使用 rowStart/rowEnd 和 columnStart/columnEnd 实现不规则网格滚动网格设置 rowsTemplate 或 columnsTemplate 实现水平/垂直滚动≈代码控制使用 Scroller 控制器实现代码控制滚动实战技巧使用Builder 装饰器拆分复杂布局提高代码可读性利用 Array.from({ length: n })快速生成测试数据合理设置 GridItem 的宽高优化滚动性能 推荐资料官方文档Grid 组件开发指南组件参考Grid API 文档我是盐焗西兰花≈不教理论只给你能跑的代码和避坑指南。≈下期见