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, // 宽 比 高
)
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,847评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,208评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,587评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,942评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,332评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,587评论 1 218
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,853评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,568评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,273评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,542评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,033评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,373评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,031评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,073评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,830评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,628评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,537评论 2 269

推荐阅读更多精彩内容