Stack
Flutter 的层叠布局是 Stack,层叠布局允许子 Widget 堆叠(按照代码中声明的顺序),同时子 Widget 可以根据到父容器四个边的位置来确定本身的位置。
Stack 是层叠布局,其子 Widget 会按照添加顺序确定显示层级,后面添加的会覆盖在前面添加的 Widget 上面。
Stack 的快速上手
给 Stack 的 子 Widget 添加内容:
Stack(children: <Widget>[Image.asset("images/flutter.png",width: 200,fit: BoxFit.cover,),Text('Hello Flutter',style: TextStyle(fontSize: 50.0),),],)
Stack 在一个页面使用的完整 Demo 为:
import 'package:flutter/material.dart';void main() => runApp(StackWidget());class StackWidget extends StatelessWidget {@overrideWidget build(BuildContext context) {return MaterialApp(title: "Flutter Demo",theme: ThemeData(primaryColor: Colors.blue,),home: Scaffold(appBar: AppBar(title: Text("Flutter布局Widget -- 层叠布局")),body: Stack(children: <Widget>[Image.asset("images/flutter.png",width: 200,fit: BoxFit.cover,),Text('Hello Flutter',style: TextStyle(fontSize: 50.0),),],),),);}}
运行效果为:

Stack 的构造函数及参数说明
Stack 的构造函数为:
class Stack extends MultiChildRenderObjectWidget {Stack({Key key,this.alignment = AlignmentDirectional.topStart,this.textDirection,this.fit = StackFit.loose,this.overflow = Overflow.clip,List<Widget> children = const <Widget>[],}) : super(key: key, children: children);...}
| 参数名字 | 参数类型 | 意义 | 必选 or 可选 |
|---|---|---|---|
| key | Key | Widget 的标识 | 可选 |
| alignment | AlignmentDirectional | 决定如何对齐 non-positioned 子 Widget 和部分 positioned 子Widget,默认值为 AlignmentDirectional.topStart 部分 positioned 子Widget,在某一个轴上没有定义的,这个轴就使用 alignment 的值,比如 left、right 为横轴,left 和 right 都没有定义,就是横轴没有定义,只要这两个一个有值,这个轴就算有值;top、bottom 为纵轴,同理。 |
可选 |
| textDirection | TextDirection | 用于确定 alignment 的对齐方向 | 可选 |
| fit | StackFit | 此参数用于决定 non-positioned 子 Widget 如何去适应 Stack 的大小 | 可选 |
| overflow | Overflow | 决定如何显示超出 Stack显示空间的子 widget | 可选 |
| children | List< Widget> | Stack 布局里排列的内容 | 可选 |
alignment:对齐方式,alignment 的类型是 AlignmentDirectional,注意这里 start 和 end 指的是 textDirection 给定的方向。
| AlignmentDirectional 的值 | 含义 |
|---|---|
| AlignmentDirectional.topStart | 上边 start 对齐 |
| AlignmentDirectional.topCenter | 上边 居中 对齐 |
| AlignmentDirectional.topEnd | 上边 end 对齐 |
| AlignmentDirectional.centerStart | 中间 start 对齐 |
| AlignmentDirectional.center | 中间 对齐 |
| AlignmentDirectional.centerEnd | 中间 end 对齐 |
| AlignmentDirectional.bottomStart | 下边 start 对齐 |
| AlignmentDirectional.bottomCenter | 下边 居中 对齐 |
| AlignmentDirectional.bottomEnd | 下边 end 对齐 |

fit:non-positioned 子 Widget 如何去适应 Stack 的大小,fit 的类型是 StackFit:
| StackFit 的值 | 含义 |
|---|---|
| StackFit.loose | 使用子 Widget 自身的大小 |
| StackFit.expand | 子 Widget 扩伸到 Stack 的大小 |
| StackFit.passthrough | Stack 的 父 Widget 的约束无修改的传递给 Stack 的子 Widget |
overflow:如何显示超出 Stack 显示空间的子 widget,overflow 的类型为 Overflow:
| Overflow 的值 | 含义 |
|---|---|
| Overflow.visible | 超出部分仍能看见 |
| Overflow.clip | 超出部分会被剪裁 |
Stack 的子 Widget
为了确定子 Widget 到父容器四个角的位置,Stack 将子 Widget 分为两类:
- positioned 子 Widget
positioned 子 Widget 是指被Positioned嵌套起来的 Widget,Positioned可以控制子 Widget 到父容器四个边的距离。 - non-positioned 子 Widget
non-positioned 子 Widget 就是不用Positioned嵌套起来的 Widget,non-positioned 子 Widget 使用 Stack 设置的 alignment 来确定自己在父容器里的位置。
Positioned
Positioned 的快速上手
Positioned 在 Stack 里使用的代码 Demo 如下:
import 'package:flutter/material.dart';void main() => runApp(StackWidget());class StackWidget extends StatelessWidget {@overrideWidget build(BuildContext context) {return MaterialApp(title: "Flutter Demo",theme: ThemeData(primaryColor: Colors.blue,),home: Scaffold(appBar: AppBar(title: Text("Flutter布局Widget -- 层叠布局")),body: Stack(fit: StackFit.expand,children: <Widget>[Positioned(left: 50,top: 100,child: Image.asset("images/flutter.png",width: 200,fit: BoxFit.cover,),),Text('Hello Flutter'),],),),);}}
运行效果为:

Positioned 的构造函数及参数说明
Positioned 的构造函数为:
class Positioned extends ParentDataWidget<Stack> {const Positioned({Key key,this.left,this.top,this.right,this.bottom,this.width,this.height,@required Widget child,}) : assert(left == null || right == null || width == null),assert(top == null || bottom == null || height == null),super(key: key, child: child);...}
| 参数名字 | 参数类型 | 意义 | 必选 or 可选 |
|---|---|---|---|
| key | Key | Widget 的标识 | 可选 |
| left | double | 离 Stack 左边的距离 | 可选 |
| top | double | 离 Stack 上边的距离 | 可选 |
| right | double | 离 Stack 右边的距离 | 可选 |
| bottom | double | 离 Stack 底边的距离 | 可选 |
| width | double | 指定 Widget 的宽度 | 可选 |
| height | double | 指定 Widget 的高度 | 可选 |
| children | List | Stack 布局里排列的内容 | 可选 |
注意,此处的 width、height 是用于配合 left、top 、right、 bottom 来定位 Widget 的。举个例子,在水平方向上,你只能指定 left、right、width 三个属性中的两个,如指定 left 和 width 后,right 会自动算出 (left+width),如果同时指定三个属性则会报错,垂直方向同理。
参考
【1】Flutter 实战
【2】Flutter 中文文档
【3】Flutter 完全手册
