本文是总结 Flutter 的的布局方式。
简单的布局控件
Align
1 2 3 4 5 6 7 8 9 | Container( child: Align( alignment: Alignment.center,// 对齐方式 widthFactor: 2.0,// 宽度因子,如果设置了宽度因子,则宽度会按照子节点的宽度*宽度因子数 heightFactor: 4.0,// 高度因子,同上 child: Text("test"),// 子控件 ), color: Colors.blue, ) |
Center
继承于 Align,alignment: Alignment.center。
1 2 3 4 5 6 7 8 | Container( child: Center( widthFactor: 2.0,// 宽度因子,如果设置了宽度因子,则宽度会按照子节点的宽度*宽度因子数 heightFactor: 4.0,// 高度因子,同上 child: Text("test"),// 子控件 ), color: Colors.blue, ) |
Padding
用于设置内边距
1 2 3 4 5 6 7 | Container( child: Padding( padding: EdgeInsets.fromLTRB(10, 10, 10, 10),// 设置内边距 child: Text("test"),// 子控件 ), color: Colors.blue, ) |
Flex 流式布局
Row 和 Column:横向流式布局、纵向流式布局
1 2 3 4 5 6 7 8 9 10 | 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>[], }) |
mainAxisAlignment:子控件的对齐方式,默认start
- start:将children放置在主轴的起点;
- center:将children放置在主轴的中心;
- end:将children放置在主轴的末尾;
- spaceAround:将主轴方向上的空白区域均分,使得children之间的空白区域相等,但是首尾child的空白区域为1/2;
- spaceBetween:将主轴方向上的空白区域均分,使得children之间的空白区域相等,首尾child都靠近首尾,没有间隙;
- spaceEvenly:将主轴方向上的空白区域均分,使得children之间的空白区域相等,包括首尾child;
mainAxisSize:控件占有空间
- MainAxisSize.max:占满父控件
- MainAxisSize.min:子控件大小
crossAxisAlignment:子控件的对齐方式,默认center
- CrossAxisAlignment.center:居中对齐
- CrossAxisAlignment.start:顶部对齐(Row)、左边对齐(Column)
- CrossAxisAlignment.end:底部对齐(Row)、右边对齐(Column)
- CrossAxisAlignment.baseline:根据baseline对齐(只对Row生效)
- CrossAxisAlignment.stretch:撑满高度(Row)、撑满宽度(Column)
textDirection:兼容阿拉伯语的从右往左
- TextDirection.ltr:默认,从左往右
- TextDirection.rtl:从右往左
verticalDirection:children摆放顺序,默认是down
- VerticalDirection.down:从上往下
- VerticalDirection.up:从下往上
textBaseline:文字对齐方式
- TextBaseline.ideographic:用于对齐字母字符的字形底部的水平线。
- TextBaseline.alphabetic:用于对齐表意字符的水平线。
Expanded:用于约束流式布局的大小
1 2 3 4 5 6 | Row( children: <Widget>[ Expanded(flex: 2, child: Text("test1")), Expanded(flex: 1, child: Text("text2")), ], ); |
flex:设置占据的比例
Standard widgets
Container
向 widget 增加 padding、margins、borders、background color 或者其他的装饰。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | Container({ Key key, this.alignment, // 对齐方式 this.padding, Color color, // 背景色 Decoration decoration, this.foregroundDecoration, double width, double height, BoxConstraints constraints, // 可以设置边框 this.margin, this.transform, this.child, }) |
Stack
将 widget 覆盖在另一个的上面。
1 2 3 4 5 6 7 8 | Stack({ Key key, this.alignment = AlignmentDirectional.topStart, this.textDirection, this.fit = StackFit.loose, this.overflow = Overflow.clip, List<Widget> children = const <Widget>[], }) |
GridView
将 widget 展示为一个可滚动的网格。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | GridView({ Key key, Axis scrollDirection = Axis.vertical, bool reverse = false, ScrollController controller, bool primary, ScrollPhysics physics, bool shrinkWrap = false, EdgeInsetsGeometry padding, @required this.gridDelegate, bool addAutomaticKeepAlives = true, bool addRepaintBoundaries = true, bool addSemanticIndexes = true, double cacheExtent, List<Widget> children = const <Widget>[], int semanticChildCount, }) |
示例
1 2 3 4 5 6 7 8 9 10 11 12 13 | GridView.count( crossAxisCount: 2, // 横向数量 padding: EdgeInsets.all(8), mainAxisSpacing: 8, // 子控件纵向间隔 crossAxisSpacing: 8, // 子控件横向间隔 children: <Widget>[ Container(height: 100,color: Colors.grey,), Container(height: 100,color: Colors.grey,), Container(height: 100,color: Colors.grey,), Container(height: 100,color: Colors.grey,), Container(height: 100,color: Colors.grey,), Container(height: 100,color: Colors.grey,), ]); |
ListView
将 widget 展示为一个可滚动的列表。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | ListView({ Key key, Axis scrollDirection = Axis.vertical, bool reverse = false, ScrollController controller, bool primary, ScrollPhysics physics, bool shrinkWrap = false, EdgeInsetsGeometry padding, this.itemExtent, bool addAutomaticKeepAlives = true, bool addRepaintBoundaries = true, bool addSemanticIndexes = true, double cacheExtent, List<Widget> children = const <Widget>[], int semanticChildCount, DragStartBehavior dragStartBehavior = DragStartBehavior.start, }) |
示例
1 2 3 4 5 6 7 8 9 10 11 12 | ListView.builder( padding: const EdgeInsets.all(8), itemCount: 10, itemBuilder: (BuildContext context, int index) { var entries = <String>["0","1","2","3","4","5","6","7","8","9"]; var colorCodes = <int>[0,100,200,300,400,500,600,700,800,900]; return Container( height: 100, color: Colors.amber[colorCodes[index]], child: Center(child: Text('Entry ${entries[index]}')), ); }) |
SingleChildScrollView
可以容纳一个子控件的ScrollView
1 2 3 4 5 6 7 8 9 10 11 | SingleChildScrollView({ Key key, this.scrollDirection = Axis.vertical, this.reverse = false, this.padding, bool primary, this.physics, this.controller, this.child, this.dragStartBehavior = DragStartBehavior.start, }) |
Material widgets
Card
将相关信息整理到一个有圆角和阴影的盒子中,设置子控件的圆角。
1 2 3 4 5 6 7 8 9 10 11 | Card({ Key key, this.color, this.elevation, this.shape, this.borderOnForeground = true, this.margin, this.clipBehavior, this.child, this.semanticContainer = true, }) |
ListTile
将最多三行的文本、可选的导语以及后面的图标组织在一行中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | ListTile({ Key key, this.leading, this.title, this.subtitle, this.trailing, this.isThreeLine = false, this.dense, this.contentPadding, this.enabled = true, this.onTap, this.onLongPress, this.selected = false, }) |
其他
AspectRatio 按比例显示
1 2 3 4 5 6 7 | AspectRatio( child: Image. asset( "images/example.jpg", fit: BoxFit.cover, ), aspectRatio: 3 / 2, // 宽 比 高 ) |