flutter--Wrap & Flow流式布局

flutter–Row & Column线性布局、Flex & Expanded弹性布局介绍了线性布局和弹性布局,这两种布局有时候并不能满足我们的需求,比如子Widgert的尺寸超出父Widget的时候会报错,可能我们需要的是自动排在下一行,这一篇来就看一下流式布局。

Wrap

1
2
3
4
5
6
7
8
9
10
11
12
Wrap({
Key key,
Axis direction: Axis.horizontal,
WrapAlignment alignment: WrapAlignment.start,
double spacing: 0.0,
WrapAlignment runAlignment: WrapAlignment.start,
double runSpacing: 0.0,
WrapCrossAlignment crossAxisAlignment: WrapCrossAlignment.start,
TextDirection textDirection,
VerticalDirection verticalDirection: VerticalDirection.down,
List<Widget> children: const[]
})

direction

排列方向
Axis.horizontal:横向排列(默认值)
Axis.vertical:纵向排列

alignment

这个和RowmainAxisAlignment效果是一样的,这里就不重复了,看flutter–Row & Column线性布局、Flex & Expanded弹性布局
有一点需要注意的就是Wrap的尺寸,横向只会被子Widget撑开,纵向如果父组件有高度则是父组件的高度,这里看一下demo。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return new MaterialApp(
home: Scaffold(
body: Container(
child: Wrap(
alignment: WrapAlignment.spaceAround,
children: <Widget>[
Container(
width: 100,
height: 50,
color: Colors.red,
),
Container(
width: 100,
height: 50,
color: Colors.blue
),
Container(
width: 100,
height: 50,
color: Colors.red,
),
Container(
width: 80,
height: 50,
color: Colors.blue
),
Container(
width: 50,
height: 50,
color: Colors.red,
),
Container(
width: 70,
height: 50,
color: Colors.blue
)
],
)
)
)
);
}
}

spacing

Widget之间的间距

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return new MaterialApp(
home: Scaffold(
body: Container(
child: Wrap(
spacing: 10,
children: <Widget>[
Container(
width: 100,
height: 50,
color: Colors.red,
),
Container(
width: 100,
height: 50,
color: Colors.blue
),
Container(
width: 100,
height: 50,
color: Colors.red,
)
],
)
)
)
);
}
}

runAlignment

一行子Widget纵向的对齐方式,属性值与alignment相同。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return new MaterialApp(
home: Scaffold(
body: Container(
height: 300,
child: Wrap(
runAlignment: WrapAlignment.spaceBetween,
children: <Widget>[
Container(
width: 100,
height: 50,
color: Colors.red,
),
Container(
width: 100,
height: 50,
color: Colors.blue
),
Container(
width: 100,
height: 50,
color: Colors.green,
),
Container(
width: 80,
height: 50,
color: Colors.yellow
),
Container(
width: 50,
height: 50,
color: Colors.pinkAccent,
),
Container(
width: 70,
height: 50,
color: Colors.deepPurple
)
],
)
)
)
);
}
}

runSpacing

每一行子Widget纵向上的间距

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return new MaterialApp(
home: Scaffold(
body: Container(
child: Wrap(
runSpacing: 10,
children: <Widget>[
Container(
width: 100,
height: 50,
color: Colors.red,
),
Container(
width: 100,
height: 50,
color: Colors.blue
),
Container(
width: 100,
height: 50,
color: Colors.green,
),
Container(
width: 80,
height: 50,
color: Colors.yellow
),
Container(
width: 50,
height: 50,
color: Colors.pinkAccent,
),
Container(
width: 70,
height: 50,
color: Colors.deepPurple
)
],
)
)
)
);
}
}

crossAxisAlignment

Widget在纵向上的对齐方式,看着好像和runAlignment一样,看demo。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return new MaterialApp(
home: Scaffold(
body: Container(
height: 300,
child: Wrap(
crossAxisAlignment: WrapCrossAlignment.center,
children: <Widget>[
Container(
width: 100,
height: 100,
color: Colors.red,
),
Container(
width: 100,
height: 50,
color: Colors.blue
),
Container(
width: 100,
height: 50,
color: Colors.green,
),
Container(
width: 80,
height: 50,
color: Colors.yellow
),
Container(
width: 50,
height: 100,
color: Colors.pinkAccent,
),
Container(
width: 70,
height: 50,
color: Colors.deepPurple
),
],
)
)
)
);
}
}


这个属性是对每一行内的Widget进行对齐操作,而runAlignment是以行为单位进行对齐操作。

textDirection

Widget横向排列方式,从左往右还是从右往左,不了解的话看这里flutter–Row & Column线性布局、Flex & Expanded弹性布局

verticalDirection

Widget纵向排列方式

Flow

1
2
3
4
5
Flow({
Key: key,
@required FlowDelegate delegate,
List<Widget> children: const[]
})

Flow的属性只有两个,都是必须的,貌似很简单,其实很复杂,children没啥说的,主要是delegate,属性值是一个函数,利用矩阵变换设置坐标来控制每一个Widget的位置。
大多数情况下Wrap已经满足需求,关于Flow就不深入来,有兴趣的话可以看官方的文档

  • © 2020-02 MonkeyInWind
  • GitHub

请我喝杯咖啡吧~