Flutter笔记(四) - Flutter的布局Widget(二)

多子布局组件

在开发中,我们经常需要将多个Widget放在一起进行布局,比如水平方向、垂直方向排列,甚至有时候需要他们进行层叠,比如图片上面放一段文字等;
这个时候我们需要使用多子布局组件(Multi-child layout widgets)。
比较常用的多子布局组件是Row、Column、Stack。

1. Flex组件

Row组件和Column组件都继承自Flex;

  • Flex组件和RowColumn属性主要的区别就是多一个 direction;
  • direction的值为Axis.horizontal的时候,则是Row,呈一行排布;
  • direction的值为Axis.vertical的时候,则是Column,呈一列排布;

它们都有主轴(Main Axis)和交叉轴(Cross Axis)的概念:

  • 对于Row来说,水平方向是主轴,竖直方向是交叉轴;


    Row@2x.png
  • 对于Column来说,竖直方向是主轴,水平方向是交叉轴;


    Column.png

2. Row组件

Row({
  Key key,
  MainAxisAlignment mainAxisAlignment = MainAxisAlignment.start, // 主轴对齐方式
  MainAxisSize mainAxisSize = MainAxisSize.max, // 水平方向尽可能大
  CrossAxisAlignment crossAxisAlignment = CrossAxisAlignment.center, // 交叉处对齐方式
  TextDirection textDirection, // 水平方向子widget的布局顺序(默认为系统当前Locale环境的文本方向(如中文、英语都是从左往右,而阿拉伯语是从右往左))
  VerticalDirection verticalDirection = VerticalDirection.down, // 表示Row纵轴(垂直)的对齐方向
  TextBaseline textBaseline, // 如果上面是baseline对齐方式,那么选择什么模式(有两种可选)
  List<Widget> children = const <Widget>[],
})

2.1. mainAxisSize

Row的特点:

  • 水平方向尽可能占据较大的空间;

  • 垂直方向包裹内容;


    WechatIMG49.jpeg
  • 如果水平方向也希望包裹内容,那么设置mainAxisSize = min;


    WechatIMG48.jpeg
return RaisedButton(
        onPressed: (){
        },
      color: Colors.red,
      child: Row(
        mainAxisSize: MainAxisSize.min,
        children: [
          Icon(Icons.favorite),
          Text("收藏"),
        ],
      ),
    );

2.2. mainAxisAlignment

元素在Row主轴上的布局方式,它是一个枚举类型:

  • start :主轴开始的位置挨个摆放元素;
  • end :主轴结束的位置挨个摆放元素;
  • center :主轴的中心点对齐;
  • spaceBetween: 左右两边的间距为0,其他元素之间平分间距;
  • spaceAround:左右两边的间距是其他元素的间距的一半;
  • spaceEvenly:间距平分;
class _YZHomeContentState extends State<YZHomeContent> {
  @override
  Widget build(BuildContext context) {
    return Row(
      children: [
        Container(width: 80, height: 60, color: Colors.red,),
        Container(width: 120, height: 100, color: Colors.orange,),
        Container(width: 90, height: 80, color: Colors.blue,),
        Container(width: 50, height: 50, color: Colors.green,),
      ],
      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
    );
  }
}
WechatIMG50.jpeg

2.3. CrossAxisAlignment

 crossAxisAlignment: CrossAxisAlignment.end,

元素在Row交叉轴上的布局方式

  • start:交叉轴的起始位置对齐;
  • end:交叉轴的结束位置对齐(垂直方向是包裹内容的);
  • center:中心点对齐(默认值)
  • baseLine:基线对齐;(必须有文本才有效果)
  • stretch: 先将Row占据交叉轴尽可能大的空间,再将所有的子Widget拉伸到最大;

2.4. Expanded

空间分配:拉伸或收缩;

  • 如果控件之间有间隔:拉伸;
  • 如果控件组合宽度超过了屏幕,则压缩;


    WechatIMG943.jpeg

    如上图,间隔等分,如果想把所有间隔分配给第一个;

return  Row(
      children: [
        Expanded(
            child: Container(width: 80, height: 60, color: Colors.red,),
        ),
        Container(width: 120, height: 100, color: Colors.orange,),
        Container(width: 90, height: 80, color: Colors.blue,),
        Container(width: 50, height: 50, color: Colors.green,),
      ],
      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
      crossAxisAlignment: CrossAxisAlignment.end,
    );
  }
}

效果:

  • 第一个控件宽度做了拉伸;


    WechatIMG942.jpeg
2.4.1 flex作用
 Expanded(
       flex: 1,
       child: Container(width: 80, height: 60, color: Colors.red,),
 ),
Expanded(
        flex: 2,
        child: Container(width: 40, height: 60, color: Colors.green,),
  ),

剩余空间分配比例: 当有多个Expanded时,

  • 如果flex相等,则拉伸的宽度相同;
  • 如果flex不等,按比例拉伸,如上面flex:2控件的宽度拉伸为flex: 1宽度的2倍,原来的width数值不再起作用。

3. Column组件

同Row;


4. Stack组件

在开发中,我们多个组件很有可能需要重叠显示,比如在一张图片上显示文字或者一个按钮等。在Flutter中我们需要使用层叠布局Stack。

4.1 Stack介绍

Stack的大小默认是包裹内容的.

  • alignment:从什么位置开始排布所有的子Widget;
  • fit: expand 将子元素拉伸到尽可能大;
  • overflow:超出部分如何处理;
  Stack({
    Key key,
    this.alignment = AlignmentDirectional.topStart,
    this.textDirection,
    this.fit = StackFit.loose,
    this.overflow = Overflow.clip,
    this.clipBehavior = Clip.hardEdge,
    List<Widget> children = const <Widget>[],
  }) 

4.2 示例

class _YZHomeContentState extends State<YZHomeContent> {
  @override
  Widget build(BuildContext context) {
    return Stack(
      alignment: AlignmentDirectional.bottomCenter,
      overflow: Overflow.visible,
      children: [
        Image.asset("assets/images/image_01.png",),
        Container(width: 150, height: 50, color: Colors.red,),
        // Positioned( //文字在Stack内部相对布局调整
        //   right: 10,
        //   bottom: 20,
        //   child:
          Text("这是图片上的文字"),
        // ),
      ],
    );
  }
}

WechatIMG51.jpeg
class _YZHomeContentState extends State<YZHomeContent> {

   bool _isFavor = false;

  @override
  Widget build(BuildContext context) {
    return Stack(
      children: [
        Image.asset("assets/images/image_02.jpeg",width: MediaQuery.of(context).size.width,),
        Positioned(
          left: 0,
          right: 0,
          bottom: 0,
          child: Container(
            padding: EdgeInsets.all(8),
            color: Color.fromARGB(10, 0, 0, 0),
            child: Row(
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              children: [
                Text("这是图片上的文字描述", style: TextStyle(fontSize: 15, color: Colors.red),),
                IconButton(
                    icon: Icon(
                        Icons.favorite,
                        color: _isFavor ? Colors.red : Colors.white,
                    ),
                    onPressed: () {
                      setState(() {
                        _isFavor = !_isFavor;
                      });
                }),
              ],
            ),
          ),
        ),
      ],
    );
  }
}
WechatIMG52.jpeg
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,835评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,598评论 1 295
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,569评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,159评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,533评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,710评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,923评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,674评论 0 203
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,421评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,622评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,115评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,428评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,114评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,097评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,875评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,753评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,649评论 2 271

推荐阅读更多精彩内容

  • 为了实现界面内组件的各种排布方式,我们需要进行布局,和其他端不同的是,Flutter中因为万物皆Widget,所以...
    5e4c664cb3ba阅读 558评论 1 1
  • 一. 单子布局组件 单子布局组件的含义是其只有一个子组件,可以通过设置一些属性设置该子组件所在的位置信息等。比较常...
    张无奈阅读 330评论 0 0
  • 前言 本文的目的是为了让读者掌握不同布局类Widget的布局特点,分享一些在实际使用过程遇到的一些问题,在《Flu...
    xqqlv阅读 5,172评论 0 18
  • 一. 多子布局组件 在开发中,我们经常需要将多个Widget放在一起进行布局,比如水平方向、垂直方向排列,甚至有时...
    happy神悦阅读 385评论 0 0
  • 一. 单子布局组件 单子布局组件的含义是其只有一个子组件,可以通过设置一些属性设置该子组件所在的位置信息等。比较常...
    AlanGe阅读 359评论 0 0