Flutter:总结Row、Column、Container等布局方式

本文是总结 Flutter 的的布局方式。

简单的布局控件

Align
Container(
  child: Align(
    alignment: Alignment.center,// 对齐方式
    widthFactor: 2.0,// 宽度因子,如果设置了宽度因子,则宽度会按照子节点的宽度*宽度因子数
    heightFactor: 4.0,// 高度因子,同上
    child: Text("test"),// 子控件
  ),
  color: Colors.blue,
)
Center

继承于 Align,alignment: Alignment.center。

Container(
  child: Center(
    widthFactor: 2.0,// 宽度因子,如果设置了宽度因子,则宽度会按照子节点的宽度*宽度因子数
    heightFactor: 4.0,// 高度因子,同上
    child: Text("test"),// 子控件
  ),
  color: Colors.blue,
)
Padding

用于设置内边距

Container(
  child: Padding(
    padding: EdgeInsets.fromLTRB(10, 10, 10, 10),// 设置内边距
    child: Text("test"),// 子控件
  ),
  color: Colors.blue,
)

Flex 流式布局

RowColumn:横向流式布局、纵向流式布局
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:用于约束流式布局的大小
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 或者其他的装饰。

  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 覆盖在另一个的上面。

Stack({
    Key key,
    this.alignment = AlignmentDirectional.topStart,
    this.textDirection,
    this.fit = StackFit.loose,
    this.overflow = Overflow.clip,
    List<Widget> children = const <Widget>[],
  })
GridView

将 widget 展示为一个可滚动的网格。

  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,
  })
示例
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 展示为一个可滚动的列表。

  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,
  })
示例
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

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

将相关信息整理到一个有圆角和阴影的盒子中,设置子控件的圆角。

Card({
    Key key,
    this.color,
    this.elevation,
    this.shape,
    this.borderOnForeground = true,
    this.margin,
    this.clipBehavior,
    this.child,
    this.semanticContainer = true,
  })
ListTile

将最多三行的文本、可选的导语以及后面的图标组织在一行中。

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 按比例显示
AspectRatio(
  child: Image. asset(
    "images/example.jpg",
    fit: BoxFit.cover,
  ),
  aspectRatio: 3 / 2, // 宽 比 高
)

推荐阅读更多精彩内容