• 一起来学习flutter 的布局组件


    一、线性布局

    我们常用的线性布局主要有两个组件Row和Column。
    所谓线性布局,即指沿水平或垂直方向排列子组件。Flutter 中通过Row和Column来实现线性布局,类似于Android 中的LinearLayout控件。Row和Column都继承自Flex

    Row({
      ...  
      TextDirection textDirection,    
      MainAxisSize mainAxisSize = MainAxisSize.max,    
      MainAxisAlignment mainAxisAlignment = MainAxisAlignment.start,
      VerticalDirection verticalDirection = VerticalDirection.down,  
      CrossAxisAlignment crossAxisAlignment = CrossAxisAlignment.center,
      List children = const [],
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    二、弹性布局

    弹性布局允许子组件按照一定比例来分配父容器空间。
    flutter 中的弹性布局主要通过Flex和Expanded/Flexible来配合实现。

    Flex组件可以沿着水平或垂直方向排列子组件,如果你知道主轴方向,使用Row或Column会方便一些,因为Row和Column都继承自Flex,参数基本相同,所以能使用Flex的地方基本上都可以使用Row或Column。Flex本身功能是很强大的,它也可以和Expanded组件配合实现弹性布局。Expanded组件可以使Row、Column、Flex等子组件在其主轴方向上展开并填充可用空间
    Expanded继承于Flexible,Flexible与Expanded的相同点是都必须使用在Row、Column、Flex其中,都可用来配置子布局的比例(权重)适配。
    不同之处是Expanded会强制填充剩余留白空间,而Flexible不会强制填充

    Row(
              children: <Widget>[
                Container(
                  height: 30.0,
                  width: 48.0,
                  color: Colors.red,
                ),
                Flexible(
                  flex: 1,
                  child: Container(
                    height: 30.0,
                    width: 88.0,
                    color: Colors.green,
                  ),
                ),
              ],
            ),
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    在这里插入图片描述

    Row(
              children: <Widget>[
                Container(
                  height: 30.0,
                  width: 48.0,
                  color: Colors.red,
                ),
                Expanded(
                  flex: 1,
                  child: Container(
                    height: 30.0,
                    width: 88.0,
                    color: Colors.green,
                  ),
                ),
              ],
            ),
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    在这里插入图片描述

    三、流式布局

    使用row的时候,一行内容过多,右边就会溢出部分报错。这是因为 Row 默认只有一行,如果超出屏幕不会折行。我们把超出屏幕显示范围会自动折行的布局称为流式布局。Flutter 中通过Wrap和Flow来支持流式布局,将上例中的 Row 换成 Wrap 后溢出部分则会自动折行,
    wrap:我们可以看到 Wrap 的很多属性在Row(包括Flex和Column)中也有,如direction、crossAxisAlignment、textDirection、verticalDirection等,这些参数意义是相同的,

    Wrap({
      ...
      this.direction = Axis.horizontal,
      this.alignment = WrapAlignment.start,
      this.spacing = 0.0,
      this.runAlignment = WrapAlignment.start,
      this.runSpacing = 0.0,
      this.crossAxisAlignment = WrapCrossAlignment.start,
      this.textDirection,
      this.verticalDirection = VerticalDirection.down,
      List<Widget> children = const <Widget>[],
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
     Wrap(
              spacing: 8.0, // 主轴(水平)方向间距
              runSpacing: 4.0, // 纵轴(垂直)方向间距
              alignment: WrapAlignment.center, //沿主轴
              children: <Widget>[
                for (int i = 0; i < 8; i++)
                  Container(
                    height: 30.0,
                    color: Colors.red,
                    child: Text("我是Wrap"),
                  ),
              ],
            ),
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    在这里插入图片描述

    Flow组件
    我们一般很少会使用Flow,因为其过于复杂,需要自己实现子 widget 的位置转换,在很多场景下首先要考虑的是Wrap是否满足需求。Flow主要用于一些需要自定义布局策略或性能要求较高(如动画中)的场景。Flow有如下优点:

    性能好;Flow是一个对子组件尺寸以及位置调整非常高效的控件,Flow用转换矩阵在对子组件进行位置调整的时候进行了优化:在Flow定位过后,如果子组件的尺寸或者位置发生了变化,在FlowDelegate中的paintChildren()方法中调用context.paintChild 进行重绘,而context.paintChild在重绘时使用了转换矩阵,并没有实际调整组件位置。
    灵活;由于我们需要自己实现FlowDelegate的paintChildren()方法,所以我们需要自己计算每一个组件的位置,因此,可以自定义布局策略。
    缺点:
    使用复杂。
    Flow 不能自适应子组件大小,必须通过指定父容器大小或实现TestFlowDelegate的getSize返回固定大小。

    四、层叠布局

    层叠布局顾名思义就是,可以让widget叠加在一起。
    stack组件

    Stack({
      this.alignment = AlignmentDirectional.topStart,
      this.textDirection,
      this.fit = StackFit.loose,
      this.overflow = Overflow.clip,
      List<Widget> children = const <Widget>[],
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    alignment:此参数决定如何去对齐没有定位(没有使用Positioned)或者部分定位掉子组件。所谓部分定位,在这里特指没有在某一个轴定位:left/right为横轴,top/bottom为纵轴,只要包含某个轴上的一个定位属性就算在该轴上有定位。
    textDireaction:和Row、Wrap的textDirection功能一样,都用于确定alignment对齐的参考系,即:textDirection的值为TextDirection.ltr,则alignment的start代表左,end代表右,即从左往右的顺序;textDirection的值为TextDirection.rtl,则alignment的start代表右,end代表左,即从右往左的顺序。
    fit:此参数用于确定没有定位的子组件如何去适应Stack的大小。StackFit.loose表示使用子组件的大小,StackFit.expand表示扩伸到Stack的大小。
    overflow:此属性决定如何显示超出Stack显示空间的子组件;值为Overflow.clip时,超出部分会被剪裁(隐藏),值为Overflow.visible 时则不会。

    Positioned组件

    const Positioned({
      Key key,
      this.left, 
      this.top,
      this.right,
      this.bottom,
      this.width,
      this.height,
      @required Widget child,
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    left、top 、right、 bottom分别代表离Stack左、上、右、底四边的距离。width和height用于指定需要定位元素的宽度和高度。注意,Positioned的width、height 和其它地方的意义稍微有点区别,此处用于配合left、top 、right、 bottom来定位组件,举个例子,在水平方向时,你只能指定left、right、width三个属性中的两个,如指定left和width后,right会自动算出(left+width),如果同时指定三个属性则会报错,垂直方向同理。

    Container(
            height: 400,
            width: double.infinity,
            child: Stack(
              alignment: Alignment.center,
              children: <Widget>[
                Container(
                  height: 30.0,
                  color: Colors.red,
                  child: Text("我是Stack"),
                ),
                Positioned(
                  top: 50,
                  left: 100,
                  child: Container(
                    height: 50,
                    width: 50,
                    color: Colors.red,
                  ),
                )
              ],
            ),
          ),
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    看效果图:
    在这里插入图片描述

    五、相对布局

    Align组件

    Align({
      Key key,
      this.alignment = Alignment.center,
      this.widthFactor,
      this.heightFactor,
      Widget child,
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    alignment : 需要一个AlignmentGeometry类型的值,表示子组件在父组件中的起始位置。AlignmentGeometry 是一个抽象类,它有两个常用的子类:Alignment和 FractionalOffset,我们将在下面的示例中详细介绍。
    widthFactor和heightFactor是用于确定Align 组件本身宽高的属性;它们是两个缩放因子,会分别乘以子元素的宽、高,最终的结果就是Align 组件的宽高。如果值为null,则组件的宽高将会占用尽可能多的空间。

     Container(
            height: 400,
            color: Colors.blue,
            width: double.infinity,
            child: Align(
              alignment: Alignment.center,
              child: Container(
                height: 30.0,
                color: Colors.red,
                child: Text("我是Align"),
              ),
            ),
          ),
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    在这里插入图片描述

    六、总结

    写了那么多布局组件,算是写完了。我们要根据不同的场景使用相应的布局组件,聪明的你一定会很快就掌握的。如果对你有用的话,麻烦手动点个赞,你的赞就是我写下去的动力。

  • 相关阅读:
    机器学习之单层神经网络的训练:增量规则(Delta Rule)
    学校介绍静态HTML网页设计作品 DIV布局学校官网模板代码 DW大学网站制作成品下载 HTML5期末大作业
    K8s学习笔记——认识理解篇
    基于webapi的websocket聊天室(番外一)
    Ansible 中的copy 复制模块应用详解
    Nginx 学习(八)Nginx实现用IP测试灰度发布
    XX市消防救援指挥中心实战指挥平台多链路聚合解决方案实例
    [React源码解析] React的设计理念和源码架构 (一)
    MySQL Exception -- Install/Remove of the Service Denied!
    umi浅用
  • 原文地址:https://blog.csdn.net/hjjdehao/article/details/126012159