Flutter 组件 | Flex 弹性布局
1.Flex的属性一览
Flex 是 Column 和 Row 的父类,其中 Row 的 direction 是水平, Column是竖直。其他的属性都是类似的,相当于 Flex 的简化版。
属性名 | 类型 | 默认值 | 简介 |
---|---|---|---|
direction | Axis | @required | 轴向 |
mainAxisAlignment | MainAxisAlignment | start | 主轴方向对齐方式 |
crossAxisAlignment | CrossAxisAlignment | center | 交叉轴方向对齐方式 |
mainAxisSize | MainAxisSize | max | 主轴尺寸 |
textDirection | TextDirection | null | 文本方向 |
verticalDirection | VerticalDirection | down | 竖直方向 |
textBaseline | TextBaseline | null | 基线类型 |
children | List |
[] |
内部孩子 |
2.轴向: direction
1enum Axis {
2 horizontal,//水平
3 vertical,//竖直
4}
也就是水平排放还是竖直排放,可以看出默认情况下都是主轴顶头,交叉轴居中
比如horizontal下主轴为水平轴,交叉轴则为竖直。也就是水平顶头,竖直居中

1var direction =[Axis.horizontal,Axis.vertical];
2var show = MultiShower(direction,(e){
3 return Flex(
4 direction: e,
5 children: [redBox,blueBox,yellowBox,greenBox],
6
7 );
8},color: Colors.black12,width: 300,height: 200);
9
10var redBox= Container(
11 color: Colors.red,
12 height: 50,
13 width: 50,
14);
15
16var blueBox= Container(
17 color: Colors.blue,
18 height: 30,
19 width: 60,
20);
21
22var yellowBox= Container(
23 color: Colors.yellow,
24 height: 50,
25 width: 100,
26);
27
28var greenBox= Container(
29 color: Colors.green,
30 height: 60,
31 width: 60,
32);
3.主轴方向: mainAxisAlignment
主轴方向的排布规则,这里以水平为例,主轴为水平方向。竖直类比即可
1enum MainAxisAlignment {
2 start,//顶头
3 end,//接尾
4 center,//居中
5 spaceBetween,//顶头接尾,其他均分
6 spaceAround,//中间的孩子均分,两头的孩子空一半
7 spaceEvenly,//均匀平分

1testMainAxisAlignment(){
2 var redBox= Container(
3 color: Colors.red,
4 height: 50,
5 width: 50,
6 );
7
8 var blueBox= Container(
9 color: Colors.blue,
10 height: 30,
11 width: 60,
12 );
13
14 var yellowBox= Container(
15 color: Colors.yellow,
16 height: 10,
17 width: 10,
18 );
19
20 var greenBox= Container(
21 color: Colors.green,
22 height: 50,
23 width: 10,
24 );
25
26 var mainAxisAlignment =[
27 MainAxisAlignment.start,MainAxisAlignment.center,
28 MainAxisAlignment.end,MainAxisAlignment.spaceAround,
29 MainAxisAlignment.spaceBetween,MainAxisAlignment.spaceEvenly];
30
31 var show = MultiShower(mainAxisAlignment,(e){
32 return Flex(
33 direction: Axis.horizontal,
34 mainAxisAlignment: e,
35 children: [redBox,blueBox,yellowBox,greenBox],
36
37 );
38 },color: Colors.black12,width: 200,height: 150);
39 return show;
40}
4.交叉轴方向: crossAxisAlignment
1enum CrossAxisAlignment {
2 start,//顶头
3 end,//接尾
4 center,//居中
5 stretch,//伸展
6 baseline,//基线
7}
还是水平为例,交叉轴便是竖轴,这里可以看出他们的布局行为
其中需要注意的是 CrossAxisAlignment.baseline
使用时必须有 textBaseline
其中textBaseline确定对齐的是那种基线,分为 alphabetic
和 ideographic

1testCrossAxisAlignment(){
2 var redBox= Container(
3 color: Colors.red,
4 height: 50,
5 width: 50,
6 );
7
8 var blueBox= Container(
9 color: Colors.blue,
10 height: 30,
11 width: 60,
12 );
13
14 var yellowBox= Container(
15 color: Colors.yellow,
16 height: 10,
17 width: 10,
18 );
19
20 var greenBox= Container(
21 color: Colors.green,
22 height: 50,
23 width: 10,
24 );
25
26 var crossAxisAlignment =[CrossAxisAlignment.start,CrossAxisAlignment.center,
27 CrossAxisAlignment.end,CrossAxisAlignment.stretch,CrossAxisAlignment.baseline];
28
29 var show = MultiShower(crossAxisAlignment,(e){
30 return Flex(
31 direction: Axis.horizontal,
32 crossAxisAlignment: e,
33 textBaseline: TextBaseline.alphabetic,//基线类型
34 children: [redBox,blueBox,yellowBox,greenBox],
35
36 );
37 },color: Colors.black12,width: 200,height: 140);
38
39 return show;
40}
5.主轴尺寸: mainAxisSize
1enum MainAxisSize {
2 min,
3 max,
4}
当父容器的宽未约束,Flex默认会将自身尽可能延伸,这便是MainAxisSize.max

此时改为MainAxisSize.min时,它不会延伸自己的区域,会包裹内容

1testMainAxisSize(){
2 var redBox= Container(
3 color: Colors.red,
4 height: 50,
5 width: 50,
6 );
7
8 var blueBox= Container(
9 color: Colors.blue,
10 height: 30,
11 width: 60,
12 );
13
14 var yellowBox= Container(
15 color: Colors.yellow,
16 height: 10,
17 width: 10,
18 );
19
20 var greenBox= Container(
21 color: Colors.green,
22 height: 50,
23 width: 10,
24 );
25
26 return Center(child: Flex(
27 direction: Axis.horizontal,
28 mainAxisSize: MainAxisSize.max,
29 children: <Widget>[redBox,blueBox,yellowBox,greenBox],
30
31 ),);
32}
33
6.文字方向: textDirection
1enum TextDirection {
2 ltr,//从左到右
3 rtl,//从右到左
4}
这个非常好理解,不多言了

1testTextDirection(){
2 var redBox= Container(
3 color: Colors.red,
4 height: 50,
5 width: 50,
6 );
7
8 var blueBox= Container(
9 color: Colors.blue,
10 height: 30,
11 width: 60,
12 );
13
14 var yellowBox= Container(
15 color: Colors.yellow,
16 height: 10,
17 width: 10,
18 );
19
20 var greenBox= Container(
21 color: Colors.green,
22 height: 50,
23 width: 10,
24 );
25
26 var textDirection =[TextDirection.ltr,TextDirection.rtl];
27 var show = MultiShower(textDirection,(e){
28 return Flex(
29 direction: Axis.horizontal,
30 textDirection: e,
31 children: [redBox,blueBox,yellowBox,greenBox],
32
33 );
34 },color: Colors.black12,width: 200,height: 140);
35 return show;
36}
7.竖直方向排序: verticalDirection
1enum VerticalDirection{
2 up,
3 down,
4}

1testVerticalDirection(){
2 var redBox= Container(
3 color: Colors.red,
4 height: 50,
5 width: 50,
6 );
7
8 var blueBox= Container(
9 color: Colors.blue,
10 height: 30,
11 width: 60,
12 );
13
14 var yellowBox= Container(
15 color: Colors.yellow,
16 height: 10,
17 width: 10,
18 );
19
20 var greenBox= Container(
21 color: Colors.green,
22 height: 50,
23 width: 10,
24 );
25
26 var verticalDirection =[VerticalDirection.up,VerticalDirection.down];
27
28 var show = MultiShower(verticalDirection,(e){
29 return Flex(
30 direction: Axis.vertical,
31 verticalDirection: e
32 children: [redBox,blueBox,yellowBox,greenBox],
33
34 );
35 },color: Colors.black12,width: 200,height: 140);
36
37 return show;
38}
8.基线对齐方式: textBaseline
1enum TextBaseline {
2 alphabetic,
3 ideographic,
4}

1testTextBaseline(){
2 var redBox= Text(
3 "张风捷特烈",style: TextStyle(fontSize: 20,backgroundColor: Colors.red),
4 );
5
6 var blueBox= Text(
7 "toly",style: TextStyle(fontSize: 50,backgroundColor: Colors.blue),
8 );
9
10 var yellowBox= Text(
11 "1994",style: TextStyle(fontSize: 30,backgroundColor: Colors.green),
12 );
13
14 var textBaseline =[TextBaseline.alphabetic,TextBaseline.ideographic];
15
16 var show = MultiShower(textBaseline,(e){
17 return Flex(
18 direction: Axis.horizontal,
19 crossAxisAlignment: CrossAxisAlignment.baseline,
20 textBaseline: e,
21 children: [redBox,blueBox,yellowBox],
22 );
23 },color: Colors.black12,width: 300,height: 140);
24
25 return show;
26}
9. Expanded与Flex的搭配
要一点是关于Expanded 组件,它能与 Flex 布局结合,对孩子组件区域进行延展。
1c1:绿色 c2:红色 c3:黄色
21).Expanded--c2:c1和c3将不变,c2延伸自己占满剩余部分
32).同时Expanded--c2和c3,最终c2和c3的长度是一样的
43).同时Expanded--c1,c2和c3,最终c1,c2,c3长度都是一样的

10.用Flex布局写个小例子
下面就用一个布局来实际看一下 Flex 的使用。

首先简单的分析一下

11.由上中下三行,可以用Column
22.第一行由图标,文字和文字组成,其中两头分处左右,可以用Expanded处理
33.中间比较复杂由一个Row中包含两部分,左边是一个两行Column的内容,右边是文字
44.底部是一个Row,主轴对齐是start
布局代码
1showItem() {
2 var infoStyle = TextStyle(color: Color(0xff999999), fontSize: 13);
3 var littleStyle = TextStyle(color: Colors.black, fontSize: 16);
4
5 var top = Row(//顶部,通过Flex布局的Row进行横向排列,Expanded中间
6 children: [
7 Image.asset("images/icon_head.png", width: 20, height: 20),
8 Expanded(
9 child: Padding(
10 child: Text("张风捷特烈"),
11 padding: EdgeInsets.only(left: 4),
12 ),
13 ),
14 Text(
15 "Flutter/Dart",
16 style: infoStyle,
17 )
18 ],
19 );
20
21 var content = Column(//中间文字内容,交叉轴为start
22 mainAxisSize: MainAxisSize.min,
23 crossAxisAlignment: CrossAxisAlignment.start,
24 children: [
25 Text(
26 "[Flutter必备]-Flex布局完全解读",
27 style: littleStyle,
28 maxLines: 2,
29 overflow: TextOverflow.ellipsis,
30 ),
31 Padding(
32 child: Text("也就是水平排放还是竖直排放,可以看出默认情况下都是主轴顶头,"
33 "交叉轴居中比如horizontal下主轴为水平轴,交叉轴则为竖直。也就是水平顶头,竖直居中"
34 "这里使用MultiShower快速展示,更好的对比出不同之处",
35 style: infoStyle, maxLines: 2, overflow: TextOverflow.ellipsis),
36 padding: EdgeInsets.only(top: 5),
37 ),
38 ],
39 );
40
41 var center = Row(//中间的部分
42 children: [
43 Expanded(
44 child: Padding(
45 child: content,
46 padding: EdgeInsets.all(5),
47 )),
48 ClipRRect(
49 borderRadius: BorderRadius.all(Radius.circular(5)),
50 child: Image.asset("images/wy_300x200.jpg",
51 width: 80, height: 80, fit: BoxFit.cover),)
52 ],
53 );
54
55 var end = Row(//底部
56 children: [
57 Icon(
58 Icons.grade,
59 color: Colors.green,
60 size: 20,
61 ),
62 Text(
63 "1000W",
64 style: infoStyle,
65 ),
66 Padding(child:Icon(Icons.tag_faces, color: Colors.lightBlueAccent, size: 20),
67 padding: EdgeInsets.symmetric(horizontal: 5),),
68 Text("2000W", style: infoStyle),
69 ],
70 );
71
72 var result = Card(//总体拼合
73 child: Container(
74 height: 160,
75 color: Colors.white,
76 padding: EdgeInsets.all(10),
77 child: Column(children: [top, Expanded(child: center), end])));
78 return result;
79}