前端开发进阶篇——Flutter布局

举报
小团子999 发表于 2020/07/02 14:58:45 2020/07/02
【摘要】 1. 线性布局(Row和Column) 线性布局,即指沿水平或垂直方向排布子组件。Flutter中通过Row和Column来实现线性布局,Row和Column都继承自Flex。Row控件可以分为灵活排列和非灵活排列两种。 Row(Column)可以在水平方向排列其子widget,其定义为: Row({ ... TextDire...

1. 线性布局(Row和Column)

        线性布局,即指沿水平或垂直方向排布子组件。Flutter中通过Row和Column来实现线性布局,Row和Column都继承自Flex。Row控件可以分为灵活排列和非灵活排列两种。

        Row(Column)可以在水平方向排列其子widget,其定义为:

    Row({    
      ...  
      TextDirection textDirection,    
      MainAxisSize mainAxisSize = MainAxisSize.max,    
      MainAxisAlignment mainAxisAlignment = MainAxisAlignment.start,
      VerticalDirection verticalDirection = VerticalDirection.down,  
      CrossAxisAlignment crossAxisAlignment = CrossAxisAlignment.center,
      List<Widget> children = const <Widget>[],})
  • textDirection:表示水平方向子组件的布局顺序(是从左往右还是从右往左)。

  • mainAxisSize:表示Row在主轴(水平)方向占用的空间,默认是MainAxisSize.max,表示尽可能多的占用水平方向的空间,此时无论子widgets实际占用多少水平空间,Row的宽度始终等于水平方向的最大宽度;而MainAxisSize.min表示尽可能少的占用水平空间,当子组件没有占满水平剩余空间,则Row的实际宽度等于所有子组件占用的的水平空间;

  • mainAxisAlignment:表示子组件在Row所占用的水平空间内对齐方式。   

    1)MainAxisAlignment.start表示沿textDirection的初始方向对齐。

    2)textDirection取值为TextDirection.ltr时,则MainAxisAlignment.start表示左对齐,

    3)textDirection取值为TextDirection.rtl时表示从右对齐。

    4)而MainAxisAlignment.end和MainAxisAlignment.start正好相反;

    5)MainAxisAlignment.center表示居中对齐。

  • verticalDirection:表示Row纵轴(垂直)的对齐方向,默认是VerticalDirection.down,表示从上到下。

  • crossAxisAlignment:表示子组件在纵轴方向的对齐方式,Row的高度等于子组件中最高的子元素高度。它的取值和MainAxisAlignment:start、end、 center。不同的是crossAxisAlignment的参考系是verticalDirection,即verticalDirection值为VerticalDirection.down时,crossAxisAlignment.start指顶部对齐,verticalDirection值为VerticalDirection.up时,crossAxisAlignment.start指底部对齐;而crossAxisAlignment.end和crossAxisAlignment.start正好相反;

  • children :子组件数组。

2. 弹性布局(Flex)

        弹性布局允许子组件按照一定比例来分配父容器空间。Flutter中的弹性布局主要通过Flex和Expanded来配合实现。Flex组件可以沿着水平或垂直方向排列子组件,使用Row或Column会方便一些,因为Row和Column都继承自Flex,参数基本相同。

       例子如下:

    body:Column(  mainAxisAlignment: MainAxisAlignment.center,  children: <Widget>[    
        Center(child:Text('I am xiaotuanzi')),
        Expanded(child:Center(child:Text('I am a student'))),
        Center(child:Text('I love coding'))
      ],
    )

3. 流式布局

        如果子widget超出屏幕范围,则会报溢出错误。我们把超出屏幕显示范围会自动折行的布局称为流式布局。Flutter中通过WrapFlow来支持流式布局。

        Wrap定义如下:

    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>[],})
    • spacing:主轴方向子widget的间距

    • runSpacing:纵轴方向的间距

    • runAlignment:纵轴方向的对齐方式

4. 层叠布局 Stack、Positioned

        水平布局和垂直布局确实很好用,但是有一种情况是无法完成的,比如放入一个图片,图片上再写一些字或者放入容器。子组件可以根据距父容器四个角的位置来确定自身的位置。Flutter中使用Stack和Positioned这两个组件来配合实现绝对定位。Stack允许子组件堆叠,而Positioned用于根据Stack的四个角来确定子组件的位置。

    1)Stcak定义如下:

   Stack({        
    this.alignment = AlignmentDirectional.topStart,
    this.textDirection,
    this.fit = StackFit.loose,
    this.overflow = Overflow.clip,
     List<Widget> children = const <Widget>[],})
  • alignment:alignment属性是控制层叠的位置的。

  • textDirection:和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 时则不会。

    2)Positioned定义如下:

    const Positioned({    
      Key key,
      this.left, 
      this.top,
      this.right,
      this.bottom,
      this.width,
      this.height,
      @required Widget child,})
  • left、top 、right、 bottom分别代表离Stack左、上、右、底四边的距离。

  • width和height用于指定需要定位元素的宽度和高度。

5. 对齐与相对定位(Align)

        通过Stack和Positioned,我们可以指定一个或多个子元素相对于父元素各个边的精确偏移,并且可以重叠。但如果我们只想简单的调整一个子元素在父元素中的位置的话,使用Align组件会更简单一些。

        Align 组件可以调整子组件的位置,并且可以根据子组件的宽高来确定自身的的宽高,定义如下:

        Align({        
          Key key,
          this.alignment = Alignment.center,
          this.widthFactor,
          this.heightFactor,
          Widget child,})
  • alignment : 需要一个AlignmentGeometry类型的值,表示子组件在父组件中的起始位置。AlignmentGeometry 是一个抽象类,它有两个常用的子类:Alignment和 FractionalOffset。表示矩形内的一个点,他有两个属性xy,分别表示在水平和垂直方向的偏移。

           Alignment Widget会以矩形的中心点作为坐标原点,即Alignment(0.0, 0.0) 。x、y的值从-1到1分别代表矩形左边到右边的距离和顶部到底边的距离,因此2个水平(或垂直)单位则等于矩形的宽(或高),如Alignment(-1.0, -1.0) 代表矩形的左侧顶点,而Alignment(1.0, 1.0)代表右侧底部终点,而Alignment(1.0, -1.0) 则正是右侧顶点,即Alignment.topRight。

           Alignment可以通过其坐标转换公式将其坐标转为子元素的具体偏移坐标:

     (Alignment.x*childWidth/2+childWidth/2, Alignment.y*childHeight/2+childHeight/2),其中childWidth为子元素的宽度,childHeight为子元素高度。

  • widthFactor和heightFactor:是用于确定Align 组件本身宽高的属性;它们是两个缩放因子,会分别乘以子元素的宽、高,最终的结果就是Align 组件的宽高。如果值为null,则组件的宽高将会占用尽可能多的空间。

        FractionalOffset继承自 Alignment,它和 Alignment唯一的区别就是坐标原点不同!FractionalOffset 的坐标原点为矩形的左侧顶点。FractionalOffset的坐标转换公式为:实际偏移 = (FractionalOffse.x * childWidth, FractionalOffse.y * childHeight)。


【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。