flutter 常用布局方式

本文详细介绍了Flutter中的常用布局方式,包括单子Widget的Container、Padding、Center布局,以及多子Widget的Row、Column、Stack布局,并结合Expanded和Positioned的使用,展示了各种布局效果和属性的调整,帮助开发者更好地理解和应用Flutter布局。

一、单子 Widget 嵌套布局:

单子 Widget是指只有一个子组件的Widget,这样布局Widget有三个:Container、Padding、Center


1、Container

Container,是一种允许在其内部添加其他控件的控件,也是 UI 框架中的一个常见概念。
在 Flutter 中,Container 本身可以单独作为控件存在(比如单独设置背景色、宽高),也可以作为其他控件的父级存在:Container 可以定义布局过程中子 Widget 如何摆放,以及如何展示。与其他框架不同的是,Flutter 的 Container 仅能包含一个子 Widget。

先简单写一个Container,尺寸200x200;在内部居左上放一个子Container,尺寸80x80

  • 代码如下:
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        // Here we take the value from the MyHomePage object that was created by
        // the App.build method, and use it to set our appbar title.
        title: Text(widget.title),
      ),
      body: _container(), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }

 Container _container(){
    return Container(
      width: 200,
      height: 200,
      color: Colors.yellow,
      alignment: Alignment.topLeft,
      child: Container(
        color: Colors.red,
        width: 80,
        height: 80,
      ),
    );
  }
  • 展示效果:

a、padding

padding可以理解为是Container的"内边框",他会影响内部子控件的位置,示例代码:

  Container _container(){
    return Container(
      width: 200,
      height: 200,
      padding: EdgeInsets.all(20),
      color: Colors.yellow,
      child: Container(
        color: Colors.red,
      ),
    );
  }

上面代码把子Container的宽高限制去掉,这样它就可以尽可能的充满父Container,但是父Container有padding,导致它无法充满,效果如下:

b、margin

margin可以理解为是Container的"外边框",他会影响当前控件的位置,示例代码:

  Container _container(){
    return Container(
      width: 200,
      height: 200,
      margin: EdgeInsets.all(20),
      padding: EdgeInsets.all(20),
      color: Colors.yellow,
      child: Container(
        color: Colors.red,
      ),
    );
  }

上面代码给父Container添加了margin,效果如下:

可以看到,父Container已经不再和屏幕左上对齐,而是隔开了一段距离,这个就是margin的效果,使视图具有外边距

2、Padding

Padding 有padding和child两个参数,Padding本身不是视图,是一种布局的描述

  • 代码如下:
Padding _padding(){
    return Padding(
      padding: EdgeInsets.all(20.0),
      child: Container(
        color: Colors.red,
        width: 200,
        height: 200,
      )
    );
  }
  • 展示效果:

可以看到,由于Padding设置了padding为 EdgeInsets.all(20.0),使子组件视图的布局与它的父视图会产生20像素的间隔

3、Center

Center与Padding一样,本身不是视图,是一种布局的描述,它使子视图的位置在父视图中心

  • 代码如下:
  Center _center(){
    return Center(
        child: Container(
          color: Colors.red,
          width: 200,
          height: 200,
        )
    );
  }
  • 展示效果:

可以看到子视图的位置在父视图的正中间,这个就是Center的作用!!

二、多子 Widget 布局:

多子 Widget是指有多个子组件的Widget,这样布局Widget大致有三个:Row、Column、Stack,配合的单组件布局Widget有:Expanded、Positioned;Row、Column一般和Expanded配合使用,Stack一般和Positioned配合使用后面会详细介绍。

对于拥有多个子 Widget 的布局类容器而言,其布局行为无非就是两种规则的抽象:水平方向上应该如何布局、垂直方向上应该如何布局。如同 Android 的 LinearLayout、前端的 Flex 布局一样,Flutter 中也有类似的概念,即将子 Widget 按行水平排列的 Row,按列垂直排列的 Column,以及负责分配这些子 Widget 在布局方向(行 / 列)中剩余空间的 Expanded。


1、Row与Column

Row与Column 本身不是视图,是一种布局的描述,它表示将子组件排列在水平一行或者垂直一列,代码及效果如下:

  Row _row(){
    return Row(
      children: [
        Container(
          color: Colors.red,
          width: 40,
          height: 40,
        ),
        Container(
          color: Colors.yellow,
          width: 200,
          height: 200,
        ),
        Container(
          color: Colors.blue,
          width: 80,
          height: 80,
        )
      ],
    );
  }

 Column _column(){
    return Column(
      children: [
        Container(
          color: Colors.red,
          width: 40,
          height: 40,
        ),
        Container(
          color: Colors.yellow,
          width: 200,
          height: 200,
        ),
        Container(
          color: Colors.blue,
          width: 80,
          height: 80,
        )
      ],
    );
  }

2、Row与Column 结合Expanded使用

Expanded表示自动填满,当Container不设置width时,他就会将width自动扩展到最大,示例代码及效果如下:

  Row _row(){
    return Row(
      children: [
        Container(
          color: Colors.red,
          width: 40,
          height: 40,
        ),
        Container(
          color: Colors.yellow,
          width: 200,
          height: 200,
        ),
        Expanded(
            child:Container(
              color: Colors.blue,
              height: 80,
            )
        )
      ],
    );
  }


如图所示,最后一个Container的宽度自动填满,这个就是Expanded的布局效果。Column与Expanded结合使用就不多做介绍了。

3、Row与Column 子视图排列方式

a、mainAxisAlignment与crossAxisAlignment

于 Row 与 Column 而言,Flutter 提供了依据坐标轴的布局对齐行为,即根据布局方向划分出主轴和纵轴:主轴,表示容器依次摆放子 Widget 的方向;纵轴,则是与主轴垂直的另一个方向。

我们可以根据主轴与纵轴,设置子 Widget 在这两个方向上的对齐规则 mainAxisAlignment 与 crossAxisAlignment。比如,主轴方向 start 表示靠左对齐、center 表示横向居中对齐、end 表示靠右对齐、spaceEvenly 表示按固定间距对齐;而纵轴方向 start 则表示靠上对齐、center 表示纵向居中对齐、end 表示靠下对齐。

下图展示了在 Row 中mainAxisAlignment设置不同方向的对齐规则后的呈现效果:

下图展示了在 Row 中crossAxisAlignment设置不同方向的对齐规则后的呈现效果:

  • 部分代码示例:
  Row _row(){
    return Row(
      crossAxisAlignment: CrossAxisAlignment.end,
      children: [
        Container(
          color: Colors.red,
          width: 40,
          height: 40,
        ),
        Container(
          color: Colors.yellow,
          width: 200,
          height: 200,
        ),
        Container(
          color: Colors.blue,
          width: 80,
          height: 80,
        )
      ],
    );
  }

b、mainAxisSize

如果想让容器与子 Widget 在主轴上完全匹配,我们可以通过设置 Row 的 mainAxisSize 参数为 MainAxisSize.min,由所有子 Widget 来决定主轴方向的容器长度,即主轴方向的长度尽可能小,类似 Android 中的 wrap_content,注意,mainAxisSize只有当 mainAxisAlignment为 MainAxisAlignment.spacexxx类型的时候才会生效。

  • 当mainAxisSize为MainAxisSize.min时

  • 当mainAxisSize为MainAxisSize.max时

4、层叠 Widget 布局:Stack 与 Positioned

有些时候,我们需要让一个控件叠加在另一个控件的上面,比如在一张图片上放置一段文字,又或者是在图片的某个区域放置一个按钮。这时候,我们就需要用到层叠布局容器 Stack 了。Stack 容器与前端中的绝对定位、与iOS 中的 Frame 布局非常类似,子 Widget 之间允许叠加,还可以根据父容器上、下、左、右四个角的位置来确定自己的位置。Stack 提供了层叠布局的容器,而 Positioned 则提供了设置子 Widget 位置的能力,代码如下:

  Stack _stack(){
    return Stack(
      children: [
        Container(
          color: Colors.yellow,
          width: 200,
          height: 200,
        ),

        Positioned(
            left: 18.0,
            top: 18.0,
            child: Container(
              color: Colors.red,
              width: 40,
              height: 40,
            ),
        )
      ],
    );
  }

可以看到,虽然两个Container是平级,但是他们是叠放在一起的。Stack 控件允许其子 Widget 按照创建的先后顺序进行层叠摆放,类似于iOS addSubview,而 Positioned 控件则用来控制这些子 Widget 的摆放位置。需要注意的是,Positioned 控件只能在 Stack 中使用,在其他容器中使用会报错。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值