1. Layout (多布局)
多布局组件常见的有:
- Row
- Column
- Stack
在使用过程中,也搭配学习:
- Expand(扩张组件)
- Positioned(只在Stack中使用)
1.1 Flex 组件
- 我们即将学习的Row、Column组件都是继承自Alex组件
- Flex组件和Row、Column的区别就是多了一个direction
- 当direction = Axis.horizontal, 则为Row
- 当direction = Axis.vertical,则为Column
在学习Row 和 Column 之前,我们学习一下主轴 和 交叉轴的区别
-
Row来说,主轴 & 交叉轴
-
Column来说, 主轴 & 交叉轴
1.2 Row 一行
Row({
Key key,
MainAxisAlignment mainAxisAlignment = MainAxisAlignment.start, // 主轴对齐方式
MainAxisSize mainAxisSize = MainAxisSize.max, // 水平方向尽可能大, 默认就是max
CrossAxisAlignment crossAxisAlignment = CrossAxisAlignment.center, // 交叉处对齐方式
TextDirection textDirection, // 水平方向子widget的布局顺序(默认为系统当前Locale环境的文本方向(如中文、英语都是从左往右,而阿拉伯语是从右往左))
VerticalDirection verticalDirection = VerticalDirection.down, // 表示Row纵轴(垂直)的对齐方向
TextBaseline textBaseline, // 如果上面是baseline对齐方式,那么选择什么模式(有两种可选)
List<Widget> children = const <Widget>[],
})
/*
mainAxisSize:
表示Row在主轴(水平)方向占用的空间,默认是MainAxisSize.max,表示尽可能多的占用水平方向的空间,此时无论子widgets实际占用多少水平空间,Row的宽度始终等于水平方向的最大宽度
而MainAxisSize.min表示尽可能少的占用水平空间,当子widgets没有占满水平剩余空间,则Row的实际宽度等于所有子widgets占用的的水平空间;
mainAxisAlignment:表示子Widgets在Row所占用的水平空间内对齐方式
如果mainAxisSize值为MainAxisSize.min,则此属性无意义,因为子widgets的宽度等于Row的宽度
如果mainAxisSize值为MainAxisSize.min,则此属性无意义,因为子widgets的宽度等于Row的宽度
MainAxisAlignment.start表示沿textDirection的初始方向对齐,
如textDirection取值为TextDirection.ltr时,则MainAxisAlignment.start表示左对齐,textDirection取值为TextDirection.rtl时表示从右对齐。
而MainAxisAlignment.end和MainAxisAlignment.start正好相反;
MainAxisAlignment.center表示居中对齐。
crossAxisAlignment:表示子Widgets在纵轴方向的对齐方式
主轴
enum MainAxisAlignment {
start, // 所有视图向左边靠齐
end, // 所有视图向右边靠齐
center, // 中间紧挨着间距为0,两边一样大
spaceBetween, // 最外面两边间距为0、中间均匀
spaceAround, // 最外面两边间距小于中间均匀的间距
spaceEvenly, // 间距均匀
}
// 纵横轴
enum CrossAxisAlignment {
start, // 顶部靠齐
end, // 底部靠齐
center, // 中间平衡
stretch, // 填充
baseline, // 也是顶部靠齐
}
*/
1.2.1 RowDemo
class RowDemo extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Row(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Expanded(
flex: 1,
child: Container(color: Colors.red, height: 60),
),
Container(color: Colors.blue, width: 80, height: 90),
Container(color: Colors.green, width: 70, height: 70),
Expanded(
// 扩张Widget
flex: 3, // 弹性系数
child: Container(color: Colors.orange, height: 100),
),
],
);
}
}
1.3 Expanded 扩张填充组件
- 如果想要水平方向填充、则无需设置宽度、只需要设置高度即可,根据弹性系数来进行比例宽度填充
- flex属性,弹性系数,Row会根据两个Expanded的弹性系数来决定它们占据剩下空间的比例
1.4 Column 一列
Column({
Key key,
MainAxisAlignment mainAxisAlignment = MainAxisAlignment.start,
MainAxisSize mainAxisSize = MainAxisSize.max,
CrossAxisAlignment crossAxisAlignment = CrossAxisAlignment.center,
TextDirection textDirection,
VerticalDirection verticalDirection = VerticalDirection.down,
TextBaseline textBaseline,
List<Widget> children = const <Widget>[],
})
1.4.1 ColumnDemo
class ColumnDemo extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly, // 主轴 均匀间距对齐
crossAxisAlignment: CrossAxisAlignment.start, // 交叉轴 起始位置对齐
children: [
// Expanded(
// flex: 1,
// child: Container(color: Colors.red, width: 60),
// ),
Container(color: Colors.blue, width: 80, height: 90),
Container(color: Colors.green, width: 70, height: 70),
Container(color: Colors.orange, width: 100, height: 100),
// Expanded(
// // 扩张Widget
// flex: 1, // 弹性系数
// child: Container(color: Colors.orange, width: 100),
// ),
],
);
}
}
1.5 Stack 层叠组件
- 如果需要底部是一个Container、然后在这个Container上面放很多Widget、则可以使用Stack组件
- Positioned组件只能使用在Stack里、主要是为了指定widgte在具体哪个位置
Stack({
Key key,
this.alignment = AlignmentDirectional.topStart, // 对齐方式
this.textDirection,
this.fit = StackFit.loose,
this.overflow = Overflow.clip,
List<Widget> children = const <Widget>[],
})
/*
fit:此参数用于决定没有定位的子widget如何去适应Stack的大小。StackFit.loose表示使用子widget的大小,StackFit.expand表示扩伸到Stack的大小。
overflow:此属性决定如何显示超出Stack显示空间的子widget,值为Overflow.clip时,超出部分会被剪裁(隐藏),值为Overflow.visible 时则不会
*/
1.5.1 StackDemo
//**注意:**Positioned组件只能在Stack中使用。
class StackDemo extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Stack(
children: [
Container(
color: Colors.green,
width: MediaQuery.of(context).size.width,
height: 500,
),
Positioned(
left: 30,
top: 30,
child: Icon(Icons.favorite, size: 50, color: Colors.red),
),
Positioned(right: 20, bottom: 20, child: Text('此致 \n 敬礼')),
],
);
}
}