HarmonyOS ArkUI Stack(层叠布局)使用指南
效果
一、概述
在HarmonyOS ArkUI开发中,Stack是一种非常重要的层叠布局容器。它允许子组件按照先后顺序逐层堆叠,后面的子组件会覆盖在前面的子组件之上。Stack在实际开发中广泛应用于以下场景:
- 图片叠加水印或贴纸:底层放置背景图片,上层叠加贴纸组件。
- 悬浮按钮:在页面内容上叠加一个操作按钮。
- 遮罩层与弹窗:在页面内容上叠加半透明遮罩。
- 角标提示:在图标右上角叠加未读消息数量。
本文将从基础概念讲起,通过多个示例逐步深入,帮助你全面掌握Stack的使用方法。
官方文档参考:Stack - HarmonyOS开发者文档
二、基本概念
2.1 Stack的工作原理
Stack是一个层叠容器,子组件按照添加顺序依次入栈,后添加的子组件在视觉上位于上层(即Z轴更高)。
Stack { 子组件A // 最底层 子组件B // 中间层 子组件C // 最顶层 }2.2 Stack与Column/Row的区别
| 特性 | Column | Row | Stack |
|---|---|---|---|
| 排列方向 | 垂直方向 | 水平方向 | 层叠方向(Z轴) |
| 子组件是否重叠 | 不重叠 | 不重叠 | 可以重叠 |
| 适用场景 | 纵向列表布局 | 横向排列布局 | 叠加、覆盖布局 |
三、基本用法
3.1 最简示例
@Entry@Componentstruct StackBasicDemo{build(){Stack(){// 底层:蓝色矩形Column().width(200).height(200).backgroundColor('#4FC3F7').borderRadius(12)// 上层:文字Text('Hello Stack').fontSize(24).fontWeight(FontWeight.Bold).fontColor(Color.White)}.width('100%').height(300).justifyContent(FlexAlign.Center)}}运行效果:蓝色矩形上方居中显示白色文字 “Hello Stack”。
3.2 对齐方式
Stack 通过alignContent属性控制子组件的对齐方式,支持以下枚举值:
| 枚举值 | 说明 |
|---|---|
Alignment.TopStart | 左上角对齐 |
Alignment.Top | 顶部居中对齐 |
Alignment.TopEnd | 右上角对齐 |
Alignment.Start | 左侧居中对齐 |
Alignment.Center | 居中对齐(默认) |
Alignment.End | 右侧居中对齐 |
Alignment.BottomStart | 左下角对齐 |
Alignment.Bottom | 底部居中对齐 |
Alignment.BottomEnd | 右下角对齐 |
@Entry@Componentstruct StackAlignDemo{build(){Stack({alignContent:Alignment.TopEnd}){// 底层背景Column().width(300).height(300).backgroundColor('#E0E0E0').borderRadius(16)// 角标Text('99+').fontSize(12).fontColor(Color.White).backgroundColor('#FF5252').borderRadius(10).padding({left:6,right:6,top:2,bottom:2}).margin({top:8,right:8})}.width('100%').height(350).justifyContent(FlexAlign.Center)}}运行效果:灰色矩形右上角显示红色角标 “99+”。
3.3 层叠顺序
子组件按照在代码中的先后顺序依次层叠,后面的组件在上层:
@Entry@Componentstruct StackOrderDemo{build(){Stack(){// 第1层(最底层)Circle().width(120).height(120).fill('#FF7043').offset({x:0,y:0})// 第2层Circle().width(120).height(120).fill('#66BB6A').offset({x:40,y:0})// 第3层(最顶层)Circle().width(120).height(120).fill('#42A5F5').offset({x:80,y:0})}.width('100%').height(200)}}运行效果:三个圆形从左到右依次排列,蓝色圆形在最上层。
四、进阶用法
4.1 图片叠加贴纸效果
这是Stack最典型的应用场景之一——在图片上叠加可拖动的贴纸:
@Entry@Componentstruct StickerOnImageDemo{@StatestickerOffsetX:number=0;@StatestickerOffsetY:number=0;build(){Stack(){// 底层:背景图片Image($r('app.media.background')).width(300).height(300).objectFit(ImageFit.Cover).borderRadius(12)// 上层:可拖动贴纸Text('⭐').fontSize(40).translate({x:this.stickerOffsetX,y:this.stickerOffsetY}).gesture(PanGesture().onActionUpdate((event:GestureEvent)=>{this.stickerOffsetX+=event.offsetX;this.stickerOffsetY+=event.offsetY;}))}.width(300).height(300).clip(true)// 裁剪超出边界的内容}}4.2 使用zIndex控制层级
当需要动态调整层叠顺序时,可以使用zIndex属性:
@Entry@Componentstruct ZIndexDemo{@StateisSwapped:boolean=false;build(){Column({space:20}){Stack(){Circle().width(100).height(100).fill('#FF7043').zIndex(this.isSwapped?2:1)Circle().width(100).height(100).fill('#42A5F5').offset({x:50}).zIndex(this.isSwapped?1:2)}.width('100%').height(150)Button('切换层级').onClick(()=>{this.isSwapped=!this.isSwapped;})}}}4.3 结合clip实现裁剪效果
Stack常与.clip(true)配合使用,防止子组件内容溢出边界:
Stack(){Image($r('app.media.background')).width(200).height(200)// 贴纸可以拖动,但不会超出Stack边界Text('🎉').fontSize(36).translate({x:150,y:150})}.clip(true)// 关键:启用裁剪五、常用属性一览
| 属性 | 类型 | 说明 |
|---|---|---|
alignContent | Alignment | 子组件对齐方式,默认Alignment.Center |
justifyContent | FlexAlign | 在主轴方向上的对齐方式 |
clip | boolean | 是否裁剪超出边界的子组件 |
width/height | Length | Stack的尺寸 |
backgroundColor | ResourceColor | 背景色 |
borderRadius | Length | 圆角半径 |
六、实战示例:卡片叠加标题栏
下面实现一个带有标题栏覆盖效果的图片卡片:
@Entry@Componentstruct CardOverlayDemo{build(){Column({space:16}){Stack({alignContent:Alignment.Bottom}){// 底层:风景图片Image($r('app.media.background')).width('90%').height(240).objectFit(ImageFit.Cover).borderRadius(16)// 上层:半透明标题栏Row(){Text('风景照片').fontSize(18).fontWeight(FontWeight.Medium).fontColor(Color.White)Blank()Text('2025-06-27').fontSize(12).fontColor('rgba(255,255,255,0.7)')}.width('90%').height(48).padding({left:16,right:16}).backgroundColor('rgba(0,0,0,0.4)').borderRadius({bottomLeft:16,bottomRight:16})}.width('100%')}.width('100%').height('100%').padding({top:60})}}七、注意事项
- 性能考量:Stack中子组件数量不宜过多,每个子组件都会参与布局计算和渲染。
- 层级管理:合理使用
zIndex控制层级,避免层级混乱导致组件被意外遮挡。 - clip属性:当子组件可能超出Stack边界时,建议设置
.clip(true)防止溢出。 - 尺寸设置:Stack默认尺寸由子组件决定,建议显式设置宽高以获得稳定的布局效果。
- 事件穿透:Stack中上层组件如果透明,触摸事件可能穿透到下层,可通过
.hitTestBehavior(HitTestMode.Transparent)控制。
八、总结
Stack是ArkUI中最灵活的层叠布局容器,核心要点如下:
- 子组件按添加顺序层叠,后添加的在上层。
- 通过
alignContent控制对齐方式。 - 通过
zIndex动态控制层级。 - 通过
.clip(true)防止内容溢出。 - 适用于图片叠加贴纸、角标提示、悬浮按钮、遮罩层等场景。
掌握Stack的使用,是构建复杂HarmonyOS UI界面的基础。
认尺寸由子组件决定,建议显式设置宽高以获得稳定的布局效果。
5.事件穿透:Stack中上层组件如果透明,触摸事件可能穿透到下层,可通过.hitTestBehavior(HitTestMode.Transparent)控制。
八、总结
Stack是ArkUI中最灵活的层叠布局容器,核心要点如下:
- 子组件按添加顺序层叠,后添加的在上层。
- 通过
alignContent控制对齐方式。 - 通过
zIndex动态控制层级。 - 通过
.clip(true)防止内容溢出。 - 适用于图片叠加贴纸、角标提示、悬浮按钮、遮罩层等场景。
掌握Stack的使用,是构建复杂HarmonyOS UI界面的基础。