Flutter中的Flex布局和Web中的Flex布局非常类似,估计是借鉴了Web中Flex布局,所以很多属性和表现,都跟其相似。但是注意一点,
自身不带滚动属性,如果超出了一行,在debug下面则会显示溢出的提示
Row和Column
Row以及Column都是多子节点容器,类似Web中的某个元素其display属性为flex,实际上它们也都是Flex的子类,它们的具体实现也都是由Flex完成,只是参数不同,更具体点就是主轴方向不同,以Row为例,其构造函数如下:
Row({
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>[],
})
它们的direction属性分别为
// Row
direction: Axis.horizontal,
/// Column
direction: Axis.vertical,
MainAxisAlignment:主轴方向上的对齐方式,会对child的位置起作用,默认是start。
其中MainAxisAlignment枚举值:
- center:将children放置在主轴的中心;
- end:将children放置在主轴的末尾;
- spaceAround:将主轴方向上的空白区域均分,使得children之间的空白区域相等,但是首尾child的空白区域为1/2;
- spaceBetween:将主轴方向上的空白区域均分,使得children之间的空白区域相等,首尾child都靠近首尾,没有间隙;
- spaceEvenly:将主轴方向上的空白区域均分,使得children之间的空白区域相等,包括首尾child;
- start:将children放置在主轴的起点;
其中spaceAround、spaceBetween以及spaceEvenly的区别,就是对待首尾child的方式。其距离首尾的距离分别是空白区域的1/2、0、1。
MainAxisSize:在主轴方向占有空间的值,默认是max。
MainAxisSize的取值有两种:
- max:根据传入的布局约束条件,最大化主轴方向的可用空间;
- min:与max相反,是最小化主轴方向的可用空间;
CrossAxisAlignment:children在交叉轴方向的对齐方式,与MainAxisAlignment略有不同。
CrossAxisAlignment枚举值有如下几种:
- baseline:在交叉轴方向,使得children的baseline对齐;
- center:children在交叉轴上居中展示;
- end:children在交叉轴上末尾展示;
- start:children在交叉轴上起点处展示;
- stretch:让children填满交叉轴方向;
TextDirection:阿拉伯语系的兼容设置,一般无需处理。
VerticalDirection:定义了children摆放顺序,默认是down。
VerticalDirection枚举值有两种:
- down:从top到bottom进行布局;
- up:从bottom到top进行布局。
top对应Row以及Column的话,就是左边和顶部,bottom的话,则是右边和底部。
TextBaseline:使用的TextBaseline的方式,有两种,
- TextBaseline.alphabetic:与字母基线对齐;
- TextBaseline.ideographic:与表意字符基线对齐;
如下分别为不设置 textBaseline 属性、设置 TextBaseline.alphabetic 和 TextBaseline.ideographic,对比效果:
clipBehavior 当子组件超出容器时的裁剪行为,设置方式如下:
- Clip.none:不裁剪
- Clip.hardEdge:裁剪
- Clip.antiAlias:裁剪,抗锯齿
- Clip.antiAliasWithSaveLayer:裁剪,抗锯齿
Flexible、Expand
前面说ow以及Column都是多子节点容器,类似Web中的某个元素其display属性为flex,那么 Flexible、Spacer以及Expand就是加了flex属性的子节点
-
fit属性
Flexible 的 fit 属性默认为 FlexFit.loose,而 Expanded 继承 Flexible,其 fit 属性指定为 FlexFit.tight,可设置的 fit 属性如下:- tight:强制填充可利用的空间;
- loose:不强制填充可利用空间,Widget自身大小。
-
flex属性
Flexible 的 flex属性是弹性系数,可以类比flex-grow 对比效果如下:
Expanded 可以使 Row、Column、Flex 里面的组件填充沿着主轴可利用的空间,如果多个 Widget 都使用了 Expanded 组件,可以使用 Expanded 的 flex 属性按照比例分配主轴空间
Row(
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
Expanded(
flex: 1,
child: Container(
width: 50,
height: 50,
color: Colors.red,
child: const Center(
child: Text(
"A",
style: TextStyle(fontSize: 20, color: Colors.white),
),
)),
),
Expanded(
flex: 2,
child: Container(
width: 50, // Row Expanded下width无效
height: 50, // Column Expanded下height无效
color: Colors.green,
child: const Center(
child: Text(
"B",
style: TextStyle(fontSize: 20, color: Colors.white),
),
)),
),
Container(
width: 50,
height: 50,
color: Colors.yellow,
child: const Center(
child: Text(
"C",
style: TextStyle(fontSize: 20, color: Colors.white),
),
)),
],
);
显示效果如下:
Spacer
Spacer 用来调节 Widget 之间的间距,会占据所有的剩余空间,因此 MainAxisAlignment 的设置将无效,Spacer 的属性 flex 用于设置剩余空间的分配权重,默认值为 1,表示占据所有剩余空间,如果两个以上 Spacer 则按照 flex 分配剩余空间
class RowSamplePage1 extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Row Sample"),
centerTitle: true,
),
body: ConstrainedBox(
constraints: BoxConstraints(maxHeight: 150),
child: Row(
children: <Widget>\[
Container(
width: 80,
height: 80,
color: Colors.red,
),
Spacer(flex: 1,),
Container(
width: 80,
height: 80,
color: Colors.green,
),
Spacer(flex: 2,),
Container(
width: 80,
height: 80,
color: Colors.yellow,
),
\],
),
));
}
}