为什么需要流式布局?
流式布局:页面元素的宽度可以按照屏幕分辨率进行适配调整,但整体布局不变。
在 Flutter 中的流式布局是: Wrap
前面讲到的,在 Flex、Row、Column 中,当子 Widget 的大小超过主轴的大小后,就会报 layout 的 overflowed 错误 ,会在界面上看到黄黑色的条。
这个问题也可以用流式布局解决,将上面代码的 Row 换成 Wrap:
import 'package:flutter/material.dart';main() {runApp(new MyApp());}class MyApp extends StatelessWidget {@overrideWidget build(BuildContext context) {return new MaterialApp(title: 'Test',home: new Scaffold(appBar: new AppBar(title: new Text('Flutter 布局Widget -- 流式布局')),body: Wrap(children: <Widget>[Text('Hello Flutter ' * 100)],)));}}
运行后的效果就为:
Wrap
Wrap 会把超出屏幕显示范围的 Widget 自动换行,所以称为流式布局。
Wrap 的快速上手
Wrap 需要设置主轴方向,默认的主轴方向为水平方向,给其 children 参数添加子 Widget 即可,例如:
Wrap(direction: Axis.horizontal,children: <Widget>[...])
Wrap 在一个页面使用的完整 Demo 如下:
import 'package:flutter/material.dart';main() => runApp(new WrapWidget());class WrapWidget extends StatelessWidget {@overrideWidget build(BuildContext context) {return new MaterialApp(title: 'Test',home: new Scaffold(appBar: new AppBar(title: new Text('Flutter 布局Widget -- 流式布局')),body: Wrap(direction: Axis.horizontal,spacing: 8.0, // 主轴 方向间距runSpacing: 12.0, // 交叉轴 方向间距alignment: WrapAlignment.center,runAlignment: WrapAlignment.start,children: <Widget>[new Chip(avatar: new CircleAvatar(backgroundColor: Colors.blue, child: Text('A')),label: new Text('AAAAAAAA'),),new Chip(avatar: new CircleAvatar(backgroundColor: Colors.blue, child: Text('M')),label: new Text('BBBBBB'),),new Chip(avatar: new CircleAvatar(backgroundColor: Colors.blue, child: Text('H')),label: new Text('CCCCCCCCC'),),new Chip(avatar: new CircleAvatar(backgroundColor: Colors.blue, child: Text('J')),label: new Text('DDDDDDDD'),),new Chip(avatar: new CircleAvatar(backgroundColor: Colors.blue, child: Text('J')),label: new Text('EEEEEEEE'),),new Chip(avatar: new CircleAvatar(backgroundColor: Colors.blue, child: Text('J')),label: new Text('FFFFFFFFFFFFFFFF'),),],)));}}
运行效果:

Wrap 的构造函数及参数说明
Wrap 的构造函数为:
class Wrap extends MultiChildRenderObjectWidget {Wrap({Key key,this.direction = Axis.horizontal,this.alignment = WrapAlignment.start,this.spacing = 0.0,this.runAlignment = WrapAlignment.start,this.runSpacing = 0.0,this.crossAxisAlignment = WrapCrossAlignment.start,this.textDirection,this.verticalDirection = VerticalDirection.down,List<Widget> children = const <Widget>[],}) : super(key: key, children: children);...}
| 参数名字 | 参数类型 | 意义 | 必选 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 完全手册
