Flutter层叠布局 #
一、Stack #
1.1 基本用法 #
Stack允许子Widget层叠放置,后面的Widget会覆盖前面的。
dart
Stack({
Key? key,
AlignmentGeometry alignment = AlignmentDirectional.topStart,
TextDirection? textDirection,
StackFit fit = StackFit.loose,
Clip clipBehavior = Clip.hardEdge,
List<Widget> children = const <Widget>[],
})
Stack(
children: [
Container(
width: 200,
height: 200,
color: Colors.red,
),
Container(
width: 150,
height: 150,
color: Colors.green,
),
Container(
width: 100,
height: 100,
color: Colors.blue,
),
],
)
1.2 alignment属性 #
控制子Widget的对齐方式:
dart
Stack(
alignment: Alignment.center,
children: [
Container(width: 200, height: 200, color: Colors.red),
Container(width: 100, height: 100, color: Colors.blue),
],
)
Alignment.topLeft
Alignment.topCenter
Alignment.topRight
Alignment.centerLeft
Alignment.center
Alignment.centerRight
Alignment.bottomLeft
Alignment.bottomCenter
Alignment.bottomRight
1.3 fit属性 #
控制子Widget的尺寸:
dart
Stack(
fit: StackFit.loose,
children: [...],
)
StackFit.loose
StackFit.expand
StackFit.passthrough
1.4 clipBehavior属性 #
控制溢出裁剪:
dart
Stack(
clipBehavior: Clip.none,
children: [...],
)
Clip.none
Clip.hardEdge
Clip.antiAlias
Clip.antiAliasWithSaveLayer
二、Positioned #
2.1 基本用法 #
Positioned用于控制子Widget在Stack中的位置。
dart
Positioned({
Key? key,
double? left,
double? top,
double? right,
double? bottom,
double? width,
double? height,
Widget? child,
})
Stack(
children: [
Container(color: Colors.grey.shade200),
Positioned(
left: 20,
top: 20,
child: Container(
width: 100,
height: 100,
color: Colors.red,
),
),
Positioned(
right: 20,
bottom: 20,
child: Container(
width: 100,
height: 100,
color: Colors.blue,
),
),
],
)
2.2 填充父容器 #
dart
Stack(
children: [
Positioned.fill(
child: Container(color: Colors.red),
),
],
)
2.3 相对定位 #
dart
Stack(
children: [
Positioned(
left: 10,
right: 10,
top: 10,
bottom: 10,
child: Container(color: Colors.blue),
),
],
)
2.4 居中定位 #
dart
Stack(
children: [
Container(color: Colors.grey.shade200),
Positioned(
top: 0,
left: 0,
right: 0,
bottom: 0,
child: Center(
child: Container(
width: 100,
height: 100,
color: Colors.red,
),
),
),
],
)
三、IndexedStack #
3.1 基本用法 #
IndexedStack只显示指定索引的子Widget。
dart
IndexedStack({
Key? key,
AlignmentGeometry alignment = AlignmentDirectional.topStart,
TextDirection? textDirection,
StackFit sizing = StackFit.loose,
int index = 0,
List<Widget> children = const <Widget>[],
})
IndexedStack(
index: _currentIndex,
children: [
Container(color: Colors.red, child: Center(child: Text('Page 1'))),
Container(color: Colors.green, child: Center(child: Text('Page 2'))),
Container(color: Colors.blue, child: Center(child: Text('Page 3'))),
],
)
3.2 切换页面 #
dart
class IndexedStackDemo extends StatefulWidget {
@override
State<IndexedStackDemo> createState() => _IndexedStackDemoState();
}
class _IndexedStackDemoState extends State<IndexedStackDemo> {
int _currentIndex = 0;
@override
Widget build(BuildContext context) {
return Scaffold(
body: IndexedStack(
index: _currentIndex,
children: [
Page1(),
Page2(),
Page3(),
],
),
bottomNavigationBar: BottomNavigationBar(
currentIndex: _currentIndex,
onTap: (index) {
setState(() {
_currentIndex = index;
});
},
items: [
BottomNavigationBarItem(icon: Icon(Icons.home), label: 'Home'),
BottomNavigationBarItem(icon: Icon(Icons.search), label: 'Search'),
BottomNavigationBarItem(icon: Icon(Icons.person), label: 'Profile'),
],
),
);
}
}
四、实战示例 #
4.1 图片角标 #
dart
Stack(
children: [
Image.network(
'https://example.com/image.jpg',
width: 200,
height: 150,
fit: BoxFit.cover,
),
Positioned(
top: 8,
right: 8,
child: Container(
padding: EdgeInsets.symmetric(horizontal: 8, vertical: 4),
decoration: BoxDecoration(
color: Colors.red,
borderRadius: BorderRadius.circular(4),
),
child: Text(
'NEW',
style: TextStyle(color: Colors.white, fontSize: 12),
),
),
),
],
)
4.2 头像角标 #
dart
Stack(
children: [
CircleAvatar(
radius: 30,
backgroundImage: NetworkImage('https://example.com/avatar.jpg'),
),
Positioned(
right: 0,
bottom: 0,
child: Container(
width: 20,
height: 20,
decoration: BoxDecoration(
color: Colors.green,
shape: BoxShape.circle,
border: Border.all(color: Colors.white, width: 2),
),
),
),
],
)
4.3 卡片悬浮效果 #
dart
Stack(
clipBehavior: Clip.none,
children: [
Container(
width: 200,
height: 120,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(8),
boxShadow: [
BoxShadow(
color: Colors.black12,
blurRadius: 8,
offset: Offset(0, 4),
),
],
),
),
Positioned(
top: -20,
left: 20,
child: Container(
width: 60,
height: 60,
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.circular(8),
boxShadow: [
BoxShadow(
color: Colors.black26,
blurRadius: 8,
),
],
),
child: Icon(Icons.star, color: Colors.white),
),
),
],
)
4.4 进度条 #
dart
Stack(
children: [
Container(
height: 8,
decoration: BoxDecoration(
color: Colors.grey.shade300,
borderRadius: BorderRadius.circular(4),
),
),
FractionallySizedBox(
widthFactor: 0.7,
child: Container(
height: 8,
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.circular(4),
),
),
),
],
)
4.5 播放按钮覆盖 #
dart
Stack(
alignment: Alignment.center,
children: [
Image.network(
'https://example.com/thumbnail.jpg',
width: double.infinity,
height: 200,
fit: BoxFit.cover,
),
Container(
width: 60,
height: 60,
decoration: BoxDecoration(
color: Colors.black45,
shape: BoxShape.circle,
),
child: Icon(Icons.play_arrow, color: Colors.white, size: 36),
),
Positioned(
bottom: 8,
right: 8,
child: Container(
padding: EdgeInsets.symmetric(horizontal: 8, vertical: 4),
decoration: BoxDecoration(
color: Colors.black54,
borderRadius: BorderRadius.circular(4),
),
child: Text(
'3:45',
style: TextStyle(color: Colors.white),
),
),
),
],
)
五、总结 #
5.1 核心Widget #
| Widget | 说明 |
|---|---|
| Stack | 层叠容器 |
| Positioned | 位置控制 |
| IndexedStack | 索引显示 |
5.2 下一步 #
掌握了层叠布局后,让我们学习 样式与主题!
最后更新:2026-03-28