Stack意为层叠布局,先添加的控件在底下,后添加的控件在顶上。
Stack的结构体如下:
Stack({
Key? key,
this.alignment = AlignmentDirectional.topStart,
this.textDirection,
this.fit = StackFit.loose,
@Deprecated(
'Use clipBehavior instead. See the migration guide in flutter.dev/go/clip-behavior. '
'This feature was deprecated after v1.22.0-12.0.pre.',
)
this.overflow = Overflow.clip,
this.clipBehavior = Clip.hardEdge,
List<Widget> children = const <Widget>[],
})
我们先看下一段代码:
class _StackState extends State<StackPage> {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
alignment: Alignment.center,
child: Stack(
children: [
Container(
width: 150,
height: 150,
color: Colors.amber,
),
Container(
width: 100,
height: 100,
color: Colors.green,
),
Container(
width: 50,
height: 50,
color: Colors.blue,
),
],
),
),
),
);
}
}
效果如下:
我们可以看到Stack的默认行为有两个
1:Stack的大小是最大子控件的大小
2:Stack内部子控件默认居左上
现在我们给Stack加上
alignment: Alignment.center,//居中
可以看到控件居于中心点
下面重点讲Stack中Position的用法
先看Position的结构体
Positioned({
Key? key,
this.left,
this.top,
this.right,
this.bottom,
this.width,
this.height,
required Widget child,
})
left: child距离父控件左边的距离
top: child距离父控件顶部的距离
right: child距离父控件右边的距离
bottom: child距离父控件右边的距离
width: child的宽度
height: child的高度
child:子控件
先看下面一段代码:
class _StackState extends State<StackPage> {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
alignment: Alignment.center,
child: Stack(
alignment: Alignment.center,
children: [
Positioned(
left: 0,
child: Container(
width: 50,
height: 50,
color: Colors.amber,
),
),
],
),
),
),
);
}
}
我们设置控件距离左边为0,那么控件就紧紧贴在左边
我们现在设置距离右边50
right: 50
看到控件显示位置与预期一致
如果我们同时设置left和right呢
Positioned(
left: 50,
right: 50,
child: Container(
width: 50,
height: 50,
color: Colors.amber,
),
)
可以看到控件虽然自身设置有50的宽度,但是依然被拉伸到符合left和right的宽度,所以同时设置left和right就会强制拉伸控件的宽度
left,right,top,bttom都设置
Positioned(
left: 50,
right: 50,
top: 50,
bottom: 50,
child: Container(
width: 50,
height: 50,
color: Colors.amber,
),
)
可以看到高度也被拉伸了
下面我们再看一种情况,Stack里面有2个控件
Stack(
alignment: Alignment.center,
children: [
Positioned(
child: Container(
width: 100,
height: 100,
color: Colors.amber,
),
),
Positioned(
left: 0,
child: Container(
width: 50,
height: 50,
color: Colors.green,
),
)
],
)
可以看到绿色的控件不会到屏幕的最左边,而是只到黄色的控件最左边,
这可以看出,Stack里只有一个控件时,该控件可以随意移动,但是有多个控件时,Stack就会计算自身的大小(与最大控件宽度相同),限制里面的控件移动范围
通常情况下,我们Stack里面都不会只有一个控件,而我们想要其中一个控件在全屏范围内定位,那么我们可以这样做,
Stack(
alignment: Alignment.center,
children: [
Container(),
Positioned(
child: Container(
width: 100,
height: 100,
color: Colors.amber,
),
),
Positioned(
left: 0,
child: Container(
width: 50,
height: 50,
color: Colors.green,
),
)
],
)
我们在Stack里添加了一个Container(),Container在没有child时,默认大小会铺满全屏,这时Stack的大小也是全屏了,其中的绿色控件也自然的到了屏幕边上
更多时候我们希望子控件各自出现在我们希望的位置上,并且保持原来的大小
这是我们可以用到Align
代码如下:
class _StackState extends State<StackPage> {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
alignment: Alignment.center,
child: Stack(
alignment: Alignment.center,
children: [
Container(),
Align(
alignment: Alignment.topLeft,
child: Container(
width: 50,
height: 50,
color: Colors.amber,
),
),
Align(
alignment: Alignment.topCenter,
child: Container(
width: 50,
height: 50,
color: Colors.green,
),
),
Align(
alignment: Alignment.topRight,
child: Container(
width: 50,
height: 50,
color: Colors.blue,
),
),
Align(
alignment: Alignment.centerLeft,
child: Container(
width: 50,
height: 50,
color: Colors.lightBlueAccent,
),
),
Align(
alignment: Alignment.center,
child: Container(
width: 50,
height: 50,
color: Colors.greenAccent,
),
),
Align(
alignment: Alignment.centerRight,
child: Container(
width: 50,
height: 50,
color: Colors.deepOrangeAccent,
),
),
Align(
alignment: Alignment.bottomLeft,
child: Container(
width: 50,
height: 50,
color: Colors.deepPurpleAccent,
),
),
Align(
alignment: Alignment.bottomCenter,
child: Container(
width: 50,
height: 50,
color: Colors.blueGrey,
),
),
Align(
alignment: Alignment.bottomRight,
child: Container(
width: 50,
height: 50,
color: Colors.pinkAccent,
),
),
],
),
),
),
);
}
}
效果如下,主要有9种位置