当前位置: 首页 > news >正文

【共创季稿事节】Grid+WaterFlow混合布局-鸿蒙ArkTS实战博客

鸿蒙原生 ArkTS 布局实战:Grid + WaterFlow 混合布局(顶部网格 + 底部瀑布流)

一、引言

在移动端应用开发中,混合布局是首页设计的常见模式。典型的「顶部网格分类 + 底部瀑布流内容推荐」布局,既能高效展示多入口(Grid),又能以错落有致的卡片流(WaterFlow)承载大量内容,兼顾信息密度视觉层次

HarmonyOS NEXT 的 ArkUI 声明式框架提供了GridWaterFlow两个高性能布局容器,配合Column纵向容器,可以非常优雅地实现这一经典布局。

本文从零开始构建一个完整的示例应用,深入剖析每个组件的配置要点及混合布局的实现细节。


二、项目环境

项目版本
操作系统HarmonyOS NEXT
API 版本24(对应 SDK 7.0.0)
开发工具DevEco Studio NEXT
构建系统hvigor 6.23+
语言ArkTS(声明式 UI + 装饰器语法)

build-profile.json5中确认 SDK 配置:

{ "app": { "products": [ { "name": "default", "targetSdkVersion": "7.0.0(24)", "compatibleSdkVersion": "7.0.0(24)", "runtimeOS": "HarmonyOS" } ] } }

三、整体布局架构

我们使用三层嵌套实现完整的混合布局:

Column(根容器,撑满全屏) ├── Column(顶部网格区域) │ ├── Row ← "🔥 热门分类" 标题栏 │ └── Grid ← 2×2 固定网格(不滚动) │ ├── GridItem → 新品推荐(圆角卡片) │ ├── GridItem → 热门榜单 │ ├── GridItem → 限时特惠 │ └── GridItem → 每日签到 │ └── Column(底部瀑布流区域,layoutWeight 占满剩余空间) ├── Row ← "✨ 为你推荐" 标题栏 └── WaterFlow ← 2 列瀑布流(自管理滚动) ├── FlowItem → 卡片 1(200vp) ├── FlowItem → 卡片 2(280vp) ├── FlowItem → 卡片 3(160vp) └── ... → 共 12 项,高度 160~310vp 不等

关键设计原则

  • Grid:固定高度,不参与页面滚动——作为「顶部导航」区域,始终可见或随页面整体滚动
  • WaterFlowlayoutWeight(1)填满剩余空间,完全接管其内容区域的纵向滚动
  • Column:作为串联容器,将两个布局区域纵向排列

四、数据模型层(@Observed 装饰器)

ArkTS 中使用@Observed装饰类,使其属性变化可被 UI 观察。这是@State数组深度观测的前提。

@ObservedclassGridCategory{name:string;icon:string;color:number;constructor(name:string,icon:string,color:number){this.name=name;this.icon=icon;this.color=color;}}@ObservedclassWaterfallItem{title:string;description:string;height:number;// 卡片高度,单位 vp —— 控制瀑布流错落效果color:number;// 卡片色调constructor(title:string,description:string,height:number,color:number){this.title=title;this.description=description;this.height=height;this.color=color;}}

为什么用@Observed
在 ArkTS 中,@State装饰的数组只观测引用变化(如pushsplice、重新赋值)。当数组中对象的属性发生变化时,需要@Observed装饰该类,才能触发 UI 刷新。虽然本示例不涉及动态属性修改,但这是生产环境最佳实践。


五、顶部 Grid 网格布局详解

5.1 布局配置

Grid(){ForEach(this.gridList,(item:GridCategory)=>{GridItem(){this.GridCell(item);}},(item:GridCategory,index?:number)=>index!.toString());}.columnsTemplate('1fr 1fr')// 2 列等宽.rowsTemplate('1fr 1fr')// 2 行等高.columnsGap(12)// 列间距 12vp.rowsGap(12)// 行间距 12vp.height(180)// 固定高度,不滚动.clip(true)// 超限裁剪.padding({left:16,right:16});

5.2 关键属性解析

属性说明
columnsTemplate'1fr 1fr'两列等宽,fr是网格的弹性单位,1fr表示等分剩余空间
rowsTemplate'1fr 1fr'两行等高
columnsGap12列与列之间 12vp 间距
rowsGap12行与行之间 12vp 间距
height180固定高度——与rowsTemplate配合,确保 Grid 不自带滚动
cliptrue超出高度部分裁剪,避免与下方 WaterFlow 重叠

5.3 「固定高度不滚动」的意义

Grid组件默认拥有自己的滚动行为——当内容超出设定高度时会内部滚动。但在混合布局中,我们不希望 Grid 独立滚动,而是让整体由 WaterFlow 统一管理滚动。因此设置height(180)+clip(true),将 Grid 限制为 2×2 静态网格。

5.4 Grid 单元格(@Builder 子组件)

@BuilderGridCell(item:GridCategory){Column(){// 圆形图标背景Text(item.icon).fontSize(32).width(48).height(48).backgroundColor(Color.White).borderRadius(24);// 分类名称Text(item.name).fontSize(14).fontWeight(FontWeight.Medium).fontColor('#333333').margin({top:8});}.width('100%').height('100%').justifyContent(FlexAlign.Center).alignItems(HorizontalAlign.Center).backgroundColor(item.color).borderRadius(14).shadow({radius:6,offsetX:0,offsetY:3,color:0x22000000});}

设计要点

  • @Builder将 UI 抽取为独立子组件,避免build()方法膨胀
  • 白色圆形背景托起 emoji 图标,形成「图标在卡片中央」的视觉效果
  • 半透明阴影(0x22为 alpha 通道,对应约 13% 不透明度)增加层次感
  • .width('100%').height('100%')使单元格撑满GridItem的区域

六、底部 WaterFlow 瀑布流布局详解

6.1 布局配置

WaterFlow(){ForEach(this.waterfallList,(item:WaterfallItem)=>{FlowItem(){this.WaterfallCell(item);}},(item:WaterfallItem,index?:number)=>index!.toString());}.columnsTemplate('1fr 1fr')// 2 列等宽.columnsGap(10)// 列间距 10vp.rowsGap(10)// 行间距 10vp.layoutWeight(1)// 填满 Column 剩余空间.width('100%').padding({left:12,right:12}).backgroundColor('#F5F5F5').onReachEnd(()=>{// 触底加载更多console.info('[WaterFlow] 触底,可在此加载更多数据');}).onReachStart(()=>{// 到顶console.info('[WaterFlow] 到达顶部');}).onScrollIndex((firstIndex:number,lastIndex:number)=>{console.info(`[WaterFlow] 可见区间: [${firstIndex},${lastIndex}]`);});

6.2 核心属性解析

属性说明
columnsTemplate'1fr 1fr'两列等宽,和 Grid 语法一致
columnsGap10列间距
rowsGap10行间距(WaterFlow 中表现为垂直间距)
layoutWeight1在 Column / Row / Flex 中占据剩余比例空间
onReachEnd回调上拉加载更多的入口,适合数据分页
onReachStart回调下拉刷新判断点
onScrollIndex回调获取当前可见区间,可用于埋点或懒加载

6.3 WaterFlow 的工作原理

WaterFlow 是 ArkUI 提供的高性能瀑布流容器,其核心机制:

  1. 自动布局:按columnsTemplate分列,每个FlowItem从上到下依次排入当前最短列
  2. 按需渲染:只渲染可见区域的FlowItem,内存与性能优于手动计算位置
  3. 自管理滚动:无需外层Scroll包裹,自身处理手势滚动
  4. 高度自适应:每个FlowItem的高度独立计算,形成错落有致的「瀑布」效果

6.4 瀑布流卡片(@Builder 子组件)

@BuilderWaterfallCell(item:WaterfallItem){Column(){// 模拟图片区域Column().width('100%').height(item.height-80)// 根据 item.height 动态计算图片区.borderRadius({topLeft:12,topRight:12}).backgroundColor(item.color);// 文字内容区域Column(){Text(item.title).fontSize(15).fontWeight(FontWeight.Bold).maxLines(1).textOverflow({overflow:TextOverflow.Ellipsis});Text(item.description).fontSize(12).lineHeight(18).maxLines(2).textOverflow({overflow:TextOverflow.Ellipsis}).margin({top:4});}.padding({left:10,right:10,top:8,bottom:10}).width('100%').layoutWeight(1);}.width('100%').height(item.height)// 每个卡片独立高度.backgroundColor(Color.White).borderRadius(12).shadow({radius:4,offsetX:0,offsetY:2,color:0x15000000});}

错落感来源:12 张卡片的高度从 160vp 到 310vp 不等,WaterFlow 自动将每个卡片排入当前最短的列,产生自然的「瀑布」错落效果。

数据示例: 晨曦山峦 200vp │ 城市夜景 280vp 海洋日记 160vp │ 林间小径 240vp 星空物语 300vp │ 咖啡时光 180vp 花海漫游 260vp │ 古建筑韵 220vp 美食探索 190vp │ 极光之舞 310vp 沙漠驼铃 170vp │ 湖畔垂钓 250vp

七、混合布局的尺寸管理

7.1 layoutWeight 的妙用

本示例中最关键的尺寸管理手段是layoutWeight

Column(){// ... 顶部 Grid 区域(自然高度)}// ...(没有 layoutWeight,取自身高度)Column(){// ... 标题WaterFlow().layoutWeight(1)// WaterFlow 填满此 Column}.layoutWeight(1)// 此 Column 填满根 Column 的剩余空间

工作流程

  1. Column高度为100%(全屏)
  2. 顶部 Grid 区域按内容自然高度渲染(约 240vp)
  3. 底部 WaterFlow 区域的Column设置了.layoutWeight(1),自动占据剩余全部空间
  4. 该 Column 内部的WaterFlow同样设置了.layoutWeight(1),填满 Column 内剩余高度
  5. WaterFlow 在自己的有效区域内管理滚动,超出的卡片内容通过内部滚动查看

7.2 为什么用两层 Column?

有人可能会问:为什么不在根 Column 直接放 WaterFlow?

// ❌ 不推荐的简化写法Column(){Grid()// 顶部网格.height(180);// 固定高度WaterFlow()// 瀑布流.layoutWeight(1);// 填满剩余空间}

这种写法理论上可行,但实际使用中存在两个问题:

  1. 标题缺失:Grid 和 WaterFlow 各自需要标题栏(“热门分类”、“为你推荐”),需要额外的布局容器
  2. 样式隔离:顶部 Grid 区域有白色背景 + 圆角,底部 WaterFlow 区域有灰色背景,用两层 Column 可以天然隔离样式作用域

因此两层 Column 的结构在可维护性和视觉还原度上更优。


八、API 24 新增特性与最佳实践

HarmonyOS NEXT API 24(SDK 7.0.0)在布局方面带来以下改进:

8.1 性能优化

  • WaterFlow 的懒加载性能提升:配合LazyForEach实现真正按需渲染,千级数据量也不卡顿
  • Grid 的复用机制GridItem支持节点复用,减少频繁建销毁的开销

8.2 推荐使用 @ObservedV2 + @Trace

虽然本示例使用@Observed(它在 API 24 中仍然兼容),但 API 24 推荐使用新的装饰器体系:

@ObservedV2classWaterfallItem{@Tracetitle:string='';@Tracedescription:string='';@Traceheight:number=0;@Tracecolor:number=0;}

@ObservedV2+@Trace的粒度更细,仅标记需要观测的属性,性能开销更低。

8.3 WaterFlow onReachEnd 的分页实践

在实际项目中,onReachEnd可以配合分页加载:

@Statepage:number=1;@StateisLoading:boolean=false;WaterFlow(){// ...}.onReachEnd(()=>{if(this.isLoading)return;this.isLoading=true;this.page++;loadMoreData(this.page).then((newItems)=>{this.waterfallList.push(...newItems);this.isLoading=false;});});

九、运行效果

在 DevEco Studio 中连接模拟器或真机运行后,可以看到:

  1. 顶部:4 个彩色圆角卡片排成 2×2 网格,每个卡片中央显示图标与分类名称,底部有柔和阴影
  2. 底部:双列瀑布流卡片依次排布,卡片高度从 160vp 到 310vp 不等,左列和右列的卡片起始位置不同,形成自然的「瀑布」落差视觉效果
  3. 滚动交互:上滑时 WaterFlow 区域流畅滚动,下滑到顶触发onReachStart回调,滑到底触发onReachEnd回调
  4. 视觉层次:网格区白色背景 + 大圆角,瀑布流区浅灰背景,两者之间通过margin隔离,层次分明

十、总结

本文通过一个完整的示例,详细讲解了如何在 HarmonyOS NEXT 中使用Grid + WaterFlow + Column实现「顶部网格 + 底部瀑布流」的混合布局。

核心收获:

知识点要点
Grid 固定高度配合.clip(true)关闭内部滚动,作为静态网格区域
WaterFlow 自管理滚动layoutWeight(1)填满剩余空间,内部滚动不冲突
Column 串联两个 Column 分别承载 Grid 和 WaterFlow,样式隔离
@Builder 抽离子组件提升代码可读性与复用性
@Observed 数据模型支持深度属性变化的 UI 观测
onReachEnd 分页回调真正的上拉加载更多入口

这套布局模式适用于绝大多数移动端首页——淘宝、京东、小红书等主流应用均采用类似结构。掌握了 Grid + WaterFlow 混合布局,就掌握了鸿蒙原生开发中最常用的首页架构。


十一、参考资料

  • HarmonyOS NEXT 开发文档 - ArkUI 布局
  • WaterFlow 组件 API
  • Grid 组件 API
  • @Observed 和 @ObservedV2 装饰器



http://www.gsyq.cn/news/1524798.html

相关文章:

  • MPC8260 SCC透明模式同步机制详解与实战配置
  • 2026东莞劳力士欧米茄腕表回收推荐 本地门店行情实测结果参考 - 薛定谔的梨花猫
  • 邵阳管道疏通马桶下水道 6 家专业疏通团队精选(2026 年版) - 金修达家庭维修
  • Mac Mouse Fix完整指南:彻底解决macOS鼠标体验痛点,释放第三方鼠标全部潜力
  • 今喜良缘信息科技有限公司怎么样?以“实在”重构婚恋服务新生态 - 资讯焦点
  • 绍兴GEO优化哪家强,一家扎根绍兴的专业数字化营销服务商 - 速递信息
  • 2026深圳水贝黄金回收也卷出天际?AI光谱仪+当场打款+15年合规机构,实测6家谁更强 - 逸程
  • 2026 宁波添价收黄金,鉴定过程可录像留档,每一笔交易都能有据可查 - 薛定谔的梨花猫
  • 3步快速分解图像图层的终极免费工具:从单图到分层PSD的智能转换
  • OpenClaw+Power Apps 实战:自动生成 Power Apps 应用、连接 Excel 数据源
  • MPC8280 PCI桥架构解析:嵌入式系统高速互联与性能优化实战
  • 2026深圳罗湖福田南山龙岗五区联动:AI无损检测黄金回收,55家连锁门店报价透明 - 逸程
  • 2026南京闲置奢品包包变现实测指南|行业科普+正规门店深度测评 - 薛定谔的梨花猫
  • MPC8280硬件实现ATM反向复用(IMA)技术原理与配置详解
  • 2026 年 6 月最新!郑州电销外呼系统哪家好?综合实力排名推荐|王妍工作室稳居榜首 - 速递信息
  • 2026年吉林省吉林市软考中级系统集成课程怎么咨询?众智商学院1980元课程入口和冯老师联系方式说明 - 众智商学院官方
  • 南通管道疏通马桶下水道 精选 6 家靠谱疏通服务商(2026 最新) - 金修达家庭维修
  • WPinternals:为Windows Phone设备重新定义技术自由的边界
  • 驻马店管道疏通马桶疏通高好评正规疏通团队精选(2026 本地实测) - 金修达家庭维修
  • 2026 东莞代理记账公司实力排名 广东万创实力领先 注册公司进出口退税合规财税优质机构测评 - 变量人生001
  • 毕节管道疏通马桶疏通 本地优质服务商盘点|2026 甄选实用指南 - 金修达家庭维修
  • 3分钟掌握CAJ转PDF格式转换工具:跨平台学术文献处理神器
  • PyPDF终极指南:10分钟掌握Python PDF处理核心技能
  • 2026年6月|GEO优化服务商TOP8推荐 - 资讯焦点
  • StarRailCopilot:终极崩坏星穹铁道自动化脚本完全指南
  • 上海电商云仓:高标准仓配一体化托管服务方案 - 资讯焦点
  • 2026株洲黄金回收五大正规渠道,湘奢汇(天元店)领衔,透明无套路 - 生活测评小能手
  • MPC8260串行接口与时隙分配器配置实战与调试指南
  • 鸿蒙原生应用从0到1:备忘录模块 —— 多视图切换与搜索实战
  • 把Codex玩起来(使用CC Switch接入DeepSeek)