Flutter Stack 组件详解
简介
Stack 是 Flutter 中用于堆叠布局的组件,允许子组件堆叠在一起。它常用于实现复杂的叠加布局,如在图片上显示文字、在页面上显示浮动按钮等。
基本用法
dart
Stack(
children: <Widget>[
Container(
width: 300,
height: 300,
color: Colors.red,
),
Positioned(
left: 20,
top: 20,
child: Container(
width: 100,
height: 100,
color: Colors.blue,
),
),
Positioned(
right: 20,
bottom: 20,
child: Container(
width: 100,
height: 100,
color: Colors.green,
),
),
],
)
常用属性
alignment
未定位子组件的对齐方式。
fit
未定位子组件的适应方式。
clipBehavior
超出部分的裁剪方式。
textDirection
文本方向,影响alignment的参考方向。
定位
Positioned
精确定位子组件。
dart
Positioned(
left: 20,
top: 20,
width: 100,
height: 100,
child: Container(
color: Colors.blue,
),
)
Positioned.fill
填充整个 Stack 空间。
dart
Positioned.fill(
child: Container(
color: Colors.black.withOpacity(0.5),
),
)
Positioned.directional
根据文本方向定位。
dart
Positioned.directional(
textDirection: TextDirection.ltr,
start: 20,
top: 20,
child: Container(
color: Colors.blue,
),
)
使用场景
- 图片上显示文字或图标
- 实现浮动按钮
- 创建遮罩层
- 实现卡片叠加效果
完整示例
dart
class StackDemo extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Stack Demo'),
),
body: Center(
child: Stack(
clipBehavior: Clip.none,
children: [
// 底层卡片
Container(
width: 300,
height: 200,
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.circular(12),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.2),
blurRadius: 10,
offset: Offset(0, 5),
),
],
),
),
// 头像
Positioned(
top: -40,
left: 20,
child: Container(
padding: EdgeInsets.all(4),
decoration: BoxDecoration(
color: Colors.white,
shape: BoxShape.circle,
),
child: CircleAvatar(
radius: 40,
backgroundImage: NetworkImage(
'https://picsum.photos/200',
),
),
),
),
// 文本内容
Positioned(
top: 60,
left: 20,
right: 20,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'John Doe',
style: TextStyle(
color: Colors.white,
fontSize: 24,
fontWeight: FontWeight.bold,
),
),
SizedBox(height: 8),
Text(
'Software Developer',
style: TextStyle(
color: Colors.white.withOpacity(0.8),
fontSize: 16,
),
),
],
),
),
// 操作按钮
Positioned(
bottom: 20,
right: 20,
child: Row(
children: [
IconButton(
icon: Icon(Icons.favorite, color: Colors.white),
onPressed: () {},
),
IconButton(
icon: Icon(Icons.share, color: Colors.white),
onPressed: () {},
),
],
),
),
],
),
),
);
}
}
进阶用法
1. 响应式布局
dart
LayoutBuilder(
builder: (context, constraints) {
return Stack(
children: [
Container(
width: constraints.maxWidth,
height: constraints.maxHeight,
color: Colors.grey[200],
),
Positioned(
left: constraints.maxWidth * 0.1,
top: constraints.maxHeight * 0.1,
width: constraints.maxWidth * 0.8,
height: constraints.maxHeight * 0.8,
child: Container(
color: Colors.blue,
),
),
],
);
},
)
2. 手势交互
dart
class DraggableStack extends StatefulWidget {
@override
_DraggableStackState createState() => _DraggableStackState();
}
class _DraggableStackState extends State<DraggableStack> {
double _top = 0;
double _left = 0;
@override
Widget build(BuildContext context) {
return Stack(
children: [
Positioned(
left: _left,
top: _top,
child: GestureDetector(
onPanUpdate: (details) {
setState(() {
_left += details.delta.dx;
_top += details.delta.dy;
});
},
child: Container(
width: 100,
height: 100,
color: Colors.blue,
),
),
),
],
);
}
}
性能优化建议
- 避免使用过多的 Positioned 组件
- 合理使用 clipBehavior
- 注意子组件的重建开销
- 使用 const 构造函数优化性能
注意事项
- Stack 的大小由未定位的子组件决定
- Positioned 组件只能用于 Stack 中
- 注意层级关系,后面的子组件会覆盖前面的
- 合理��理溢出情况
总结
Stack 是实现复杂叠加布局的重要组件,通过合理使用 Positioned 可以实现灵活的定位效果。在使用时需要注意性能优化和布局规则。