在Flutter中, Stack是核心布局组件之一,主要用于叠加布局实现有一些复杂的页面效果,悬浮按钮、蒙层、徽章提示等,熟练掌握Stack基本属性,并结合其它组件灵活使用可以完成非常炫酷的页面绘制。
以下是stack组件的一些基本属性和用法介绍。
一、基本概念
Stack 允许子组件以层叠的方式排列(类似 CSS 的绝对定位),常用于叠加元素(如图标上的徽章、对话框、悬浮按钮等)。默认情况下,子组件会从左上角开始堆叠。
这应该是我们裁切图片时经常见到的一个效果。 这个示例就是通过三层层叠的效果实现的,底部是一张图片,中间是一个蒙版,最上层是一个被裁切过的图片,
二、核心属性
1. 对齐方式:alignment
控制所有子组件的默认对齐方式(未使用 Positioned 包裹的子组件):
常见值:
Alignment.topLeft(默认值)
Alignment.topCenter
Alignment.topRight
Alignment.centerLeft
Alignment.center
Alignment.centerRight
Alignment.bottomLeft
Alignment.bottomCenter
Alignment.bottomRight
Alignment(0.5, 0.5)(自定义偏移)
2. Alignment(double x, double y)偏移量计算
是一个y轴从上到下,x轴从左至右计算的方式;最大值是(1,1)左下角,最小值是(-1,-1)左上角,中间是(0,0)
Alignment(-1, -1)
Alignment(0, 0)
-Alignment(1, 1)
2. 尺寸适配:fit
控制非定位子组件(未被 Positioned 包裹的组件)如何适应 Stack 的尺寸:
StackFit.loose(默认):子组件不受约束,按自身大小显示StackFit.expand:强制子组件填满Stack的可用空间
Container(
alignment: Alignment.center,
width: 300,
height: 400,
child: Stack(
alignment: Alignment(-1, -1),
fit: StackFit.expand,
children: <Widget>[
Container(width: 200, height: 300, color: Colors.red), //被迫和父级Container一样大,并且背遮挡住了
Positioned(
child: Container(width: 100, height: 100, color: Colors.green),// 被迫和父级Container一样大
),
],
),
),
StackFit.passthrough:继承父容器的约束
Container(
alignment: Alignment.center,
width: 300,
height: 400,
child: Stack(
alignment: Alignment(-1, -1),
fit: StackFit.passthrough,
children: <Widget>[
Container(width: 200, height: 300, color: Colors.red),
Positioned(
child: Container(width: 100, height: 100, color: Colors.green),
),
],
),
),
3. 裁剪行为:clipBehavior
控制子组件溢出 Stack 时的裁剪方式:
Clip.hardEdge(默认):快速裁剪,不抗锯齿Clip.antiAlias:平滑裁剪(性能略低)Clip.none:不裁剪(可能导致溢出)
Stack(
clipBehavior: Clip.none, // 允许子组件超出Stack范围
children: [Positioned(top: -20, child: Icon(Icons.star))],
)
三、动态定位子组件
通过 Positioned 包裹子组件,实现精确的位置控制:
1. 基础定位
Stack(
children: [
Positioned(
left: 10,
top: 20,
child: Icon(Icons.notifications),
),
Positioned(
right: 0,
bottom: 0,
child: Text("End"),
),
],
)
2. 相对尺寸
Positioned.fill( // 填满父容器
child: Container(color: Colors.black12),
);
Positioned(
left: 10,
right: 10, // 左右边距各10
height: 50,
child: Container(color: Colors.red),
);
四、常见布局场景
1. 头像叠加徽章
Stack(
clipBehavior: Clip.none, // 允许徽章超出Stack
children: [
CircleAvatar(radius: 30),
Positioned(
right: -5,
bottom: -5,
child: Container(
padding: EdgeInsets.all(2),
decoration: BoxDecoration(
color: Colors.red,
shape: BoxShape.circle,
),
child: Text("3", style: TextStyle(color: Colors.white)),
),
],
)
2. 背景虚化,局部高亮
Stack(
alignment: Alignment(0, 0),
fit: StackFit.passthrough,
children: <Widget>[
Image.asset(
'assets/image/33333.jpeg', // 图片的本地地址
width: 300,
height: 400,
fit: BoxFit.none, // 图片填充方式
),
Center(
child: ClipRect(
child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: 2.0, sigmaY: 2.0),
child: Container(
width: 300,
height: 400,
decoration: BoxDecoration(color: Colors.grey.shade200.withOpacity(0.5)),
),
),
),
),
SizedBox(
width: 200,
height: 200,
child: ClipOval(
child: Image.asset(
'assets/image/33333.jpeg', // 图片的本地地址
fit: BoxFit.none,
width: 300,
height: 400,
),
)
),
],
),
2. 底部导航栏悬浮按钮
Stack(
alignment: Alignment.bottomCenter,
children: [
Scaffold(body: ...), // 页面内容
Positioned(
bottom: 30,
child: FloatingActionButton(
onPressed: () {},
child: Icon(Icons.add),
),
),
],
)
五、注意事项
- 子组件默认左上对齐:未使用
Positioned或Align的子组件会堆叠在左上角。 - 尺寸问题:如果
Stack的父容器未提供约束(如直接放在ListView中),需显式设置尺寸(如SizedBox)。 - 性能优化:避免在
Stack中嵌套过多子组件,尤其是需要动态更新的组件。 - 组合使用:常与
Positioned、Align、Transform等组件配合实现复杂效果。
六、总结
Stack 是 Flutter 中实现层叠布局的核心组件,通过 Positioned 和 Align 可灵活控制子组件的位置和层级。适用于需要元素叠加的场景(如悬浮按钮、蒙层、徽章提示等),但需注意处理溢出和尺寸约束问题。