为什么需要流式布局?

流式布局:页面元素的宽度可以按照屏幕分辨率进行适配调整,但整体布局不变。

在 Flutter 中的流式布局是: Wrap

前面讲到的,在 Flex、Row、Column 中,当子 Widget 的大小超过主轴的大小后,就会报 layout 的 overflowed 错误 ,会在界面上看到黄黑色的条。

这个问题也可以用流式布局解决,将上面代码的 Row 换成 Wrap:

  1. import 'package:flutter/material.dart';
  2. main() {
  3. runApp(new MyApp());
  4. }
  5. class MyApp extends StatelessWidget {
  6. @override
  7. Widget build(BuildContext context) {
  8. return new MaterialApp(
  9. title: 'Test',
  10. home: new Scaffold(
  11. appBar: new AppBar(title: new Text('Flutter 布局Widget -- 流式布局')),
  12. body: Wrap(
  13. children: <Widget>[Text('Hello Flutter ' * 100)],
  14. )));
  15. }
  16. }

运行后的效果就为:

Flutter 学习(二十三)流式布局 - 图1

Wrap

Wrap 会把超出屏幕显示范围的 Widget 自动换行,所以称为流式布局。

Wrap 的快速上手

Wrap 需要设置主轴方向,默认的主轴方向为水平方向,给其 children 参数添加子 Widget 即可,例如:

  1. Wrap(
  2. direction: Axis.horizontal,
  3. children: <Widget>[
  4. ...
  5. ]
  6. )

Wrap 在一个页面使用的完整 Demo 如下:

  1. import 'package:flutter/material.dart';
  2. main() => runApp(new WrapWidget());
  3. class WrapWidget extends StatelessWidget {
  4. @override
  5. Widget build(BuildContext context) {
  6. return new MaterialApp(
  7. title: 'Test',
  8. home: new Scaffold(
  9. appBar: new AppBar(title: new Text('Flutter 布局Widget -- 流式布局')),
  10. body: Wrap(
  11. direction: Axis.horizontal,
  12. spacing: 8.0, // 主轴 方向间距
  13. runSpacing: 12.0, // 交叉轴 方向间距
  14. alignment: WrapAlignment.center,
  15. runAlignment: WrapAlignment.start,
  16. children: <Widget>[
  17. new Chip(
  18. avatar: new CircleAvatar(
  19. backgroundColor: Colors.blue, child: Text('A')),
  20. label: new Text('AAAAAAAA'),
  21. ),
  22. new Chip(
  23. avatar: new CircleAvatar(
  24. backgroundColor: Colors.blue, child: Text('M')),
  25. label: new Text('BBBBBB'),
  26. ),
  27. new Chip(
  28. avatar: new CircleAvatar(
  29. backgroundColor: Colors.blue, child: Text('H')),
  30. label: new Text('CCCCCCCCC'),
  31. ),
  32. new Chip(
  33. avatar: new CircleAvatar(
  34. backgroundColor: Colors.blue, child: Text('J')),
  35. label: new Text('DDDDDDDD'),
  36. ),
  37. new Chip(
  38. avatar: new CircleAvatar(
  39. backgroundColor: Colors.blue, child: Text('J')),
  40. label: new Text('EEEEEEEE'),
  41. ),
  42. new Chip(
  43. avatar: new CircleAvatar(
  44. backgroundColor: Colors.blue, child: Text('J')),
  45. label: new Text('FFFFFFFFFFFFFFFF'),
  46. ),
  47. ],
  48. )));
  49. }
  50. }

运行效果:

Flutter 学习(二十三)流式布局 - 图2

Wrap 的构造函数及参数说明

Wrap 的构造函数为:

  1. class Wrap extends MultiChildRenderObjectWidget {
  2. Wrap({
  3. Key key,
  4. this.direction = Axis.horizontal,
  5. this.alignment = WrapAlignment.start,
  6. this.spacing = 0.0,
  7. this.runAlignment = WrapAlignment.start,
  8. this.runSpacing = 0.0,
  9. this.crossAxisAlignment = WrapCrossAlignment.start,
  10. this.textDirection,
  11. this.verticalDirection = VerticalDirection.down,
  12. List<Widget> children = const <Widget>[],
  13. }) : super(key: key, children: children);
  14. ...
  15. }
参数名字 参数类型 意义 必选 or 可选
key Key Widget 的标识 可选
direction Axis 主轴的方向
默认是 Axis.horizontal
可选
alignment WrapAlignment 子Widget 在主轴上的对齐方式,默认值为WrapAlignment.start
WrapAlignment 的值和 MainAxisAlignment 的一样
可选
runAlignment WrapAlignment Wrap 会自动换成或换列,runAlignment 就是每行或每列的对齐方式,如果主轴为水平方向,就是每行,如果主轴为竖直方向,就是每列,默认值为WrapAlignment.start
WrapAlignment 的值和 MainAxisAlignment 的一样
可选
runSpacing double 每行或每列之间的间距
默认是0.0
可选
crossAxisAlignment WrapCrossAlignment 子Widget 在交叉轴上的对齐方式,WrapCrossAlignment.start
WrapCrossAlignment 的值和 MainAxisAlignment 的一样
可选
textDirection TextDirection 表示 子Widget 在主轴方向上的布局顺序 可选
verticalDirection VerticalDirection 表示 子Widget 在交叉轴方向上的布局顺序 可选
children List< Widget> Wrap布局 里排列的内容 可选

参考

【1】Flutter 实战
【2】Flutter 中文文档
【3】Flutter 完全手册