Stack一般与Positioned配合使用,在Flutter中我们称之为层叠布局,顾名思义,它允许子Widget按照代码顺序堆叠起来。并可以利用其相关属性调整其子Widget的位置。看如下代码:
Container (
width: 300,
height: 300,
color: Colors.blue,
child: Stack(
children: [
Positioned(child: Text("顶部居左"), left: 18,),
Positioned(child: Text("底部居左"), left: 18, bottom: 18,),
Positioned(child: Text("顶部居右"), right: 18 top: 18,),
Positioned(child: Text("底部居右"), right: 18, bottom: 18,),
],
),
);
运行效果:
通过Positioned的left,top,right,bottom属性;在Stack中绝对定位到相应位置
- alignment属性
作用是确定未指定位置信息的元素的对齐方式,属于AlignmentGeometry类型(包括Alignment和AlignmentDirectional、FractionalOffset,Alignment和AlignmentDirectional使用方式相同,区别是AlignmentDirectional可以适配不同的TextDirection(ltr,rtl))。如下代码:
Container (
width: 300,
height: 300,
color: Colors.blue,
child: Stack(
// 未被Positioned包括或没有设置位置的Widget对齐方式
alignment: Alignment.center,
children: [
Text("没有Positioned"),
Positioned(child: Text("居中")),
Positioned(child: Text("顶部居左"), left: 18,),
Positioned(child: Text("底部居左"), left: 18, bottom: 18,),
Positioned(child: Text("顶部居右"), right: 18 top: 18,),
Positioned(child: Text("底部居右"), right: 18, bottom: 18,),
],
),
);
运行效果:
我们设置了alignment值为 Alignment.center。那么居左的Text,现在在垂直方向上居中了。没有设置上下左右间距的居中Widget和没有被Positioned包括的Text与相对于父Widget居中了。
- fit属性
在Stack中还有另外一个属性fit,我们可以通过fit属性来设置未指定位置的子Widget的空间大小。
fit有三个值可选:
enum StackFit {
// 使用子Widget 自身的大小
loose,
// 使子widget与stack大小一致
expand,
// stack的父widget的布局大小约束无修改的传递给 Stack 的子Widget
passthrough,
}
我们来看一下:loose
Container(
width: 300,
height: 300,
color: Colors.blue,
child: Stack(
fit: StackFit.loose,
children: [
Container(
width: 200,
height: 20,
color: Colors.orange,
child: Text("没有Positioned")
),
Positioned(child: Text("底部居左"), left: 18, bottom: 18,),
],
),
);
运行效果:
我们发现设置fit: StackFit.loose后橘色区域与设置的宽高一致,我们看设置fit: StackFit.expand的效果:
说明fit属性为 StackFit.expand时,没有设置定位的子widget会占满stack。
passthrough官方文档说明的是将stack的父widget的布局大小约束无修改的传递给 Stack 的子Widget。试过之后发现与expand效果一致,也许还有其它区别尚未发现。
- clipBehavior属性
有四个值:
enum Clip {
// 不裁剪
none,
// 裁剪,不抗锯齿
hardEdge,
// 裁剪,抗锯齿
antiAlias,
// 裁剪,抗锯齿
antiAliasWithSaveLayer,
}
当clipBehavior属性为none时,超出部分不会被裁剪;为hardEdge,antiAlias,antiAliasWithSaveLayer时,超出部分会被裁剪。默认是hardEdge。
代码如下:
Container(
width: 300,
height: 300,
color: Colors.blue,
child: Stack(
clipBehavior: Clip.none,
children: const [
Positioned(left: 250, bottom: 18,child: Text("我是一段很长很长很长很长很长很长很长很长的文字"),),
],
),
);
运行效果:
属性为hardEdge,antiAlias,antiAliasWithSaveLayer时,运行效果:
Stack的直接子类有IndexedStack,其中有一个index属性,为可见子组件的index位置。这里就不细说了。