Flutter 学习 - Widget 之 布局 Widget

前言

做Android开发的朋友知道,在进行Android开始时,我们常用到的布局有

  • LinearLayout(线性布局)
  • RelativeLayout(相对布局)
  • FrameLayout(帧布局)
  • AbsoluteLayout(绝对布局)
  • TableLayout(表格布局)
  • ConstraintLayout(约束布局)
    接下来我们看下在Flutter中的布局又有哪些来供给我们使用

正文 - 布局的分类

按照子Widget的数量进行分类:
  • 单子Widget布局:布局Widget中只能包含一个子Widget的
    如:
Center(
     child: Text("data")
)

Center就是单子Widget的布局,它的子Widget属性是child,而且只能有一个

  • 多子Widget布局:布局Widget中可以含有多个子Widget的
    如:
Column(
      children: [
          Text("data"),
          Text("data")
          ...
       ],
)

Column就是多子Widget的布局,它的子Widget属性是children,是Widget数组,可以有多个Widget

布局Widget还可以按照子元素排布的方式进行分类:
  • 弹性布局 - Flex
    先看下效果图
    Flutter 学习 - Widget 之 布局 Widget_第1张图片
    20191108160730.jpg

下面看下Flex的使用方法

 Flex(
       direction: Axis.vertical,
       mainAxisAlignment: MainAxisAlignment.spaceBetween,
       children: _getWidgets(),
 )

对应的就是效果图中的第一个排列效果
在了解Flex的构造函数前,我们需要了解在Flex的使用过程中的另外两个概念,主轴和交叉轴
看下图

Flutter 学习 - Widget 之 布局 Widget_第2张图片
WechatIMG687.jpeg

由图可见,通俗的说其实就是水平方向和垂直方向的轴线
当主轴是水平方向,交叉轴就是垂直方向
当主轴是垂直方向,交叉轴就是水平方向
了解了上图后我们下面要介绍的参数概念就好理解了

接下来我们看下Flex的构造函数

Flex({
    Key key,
    @required this.direction,//主轴的方向,类型Axis
    this.mainAxisAlignment = MainAxisAlignment.start,//子Widget在主轴的对齐方式,类型MainAxisAlignment
    this.mainAxisSize = MainAxisSize.max,//主轴应该占用多大的空间,类型MainAxisSize
    this.crossAxisAlignment = CrossAxisAlignment.center,//子Widget在交叉轴的对齐方式,类型CrossAxisAlignment
    this.textDirection,//子Widget在主轴方向上的布局顺序,类型TextDirection
    this.verticalDirection = VerticalDirection.down,//子Widget 在交叉轴方向上的布局顺序,类型VerticalDirection
    this.textBaseline,//排列子Widget时使用哪个基线,类型TextBaseline
    List children = const [],//Flex布局里面排列的内容
  }) : assert(direction != null),
     ...;

PS: 这里需要注意 direction参数是必传参数,当crossAxisAlignment为CrossAxisAlignment.baseline的时候,textBaseline也不能为空

Axis(主轴的方向)- 2种方式

  • Axis.horizontal:主轴方向为水平方向,那么 子Widget 就会沿水平方向排列,交叉轴就是垂直方向
  • Axis.vertical:主轴方向为垂直方向,那么 子Widget 就会沿垂直方向排列,交叉轴就是水平方向

MainAxisAlignment(子Widget 在主轴的对齐方式) -6种方式

  • MainAxisAlignment.start:沿着主轴的起点对齐
    textDirection 必须有值,以确定是从左边开始的还是从右边开始的
  • MainAxisAlignment.end:沿着主轴的终点对齐
    textDirection 必须有值,以确定是在左边结束的还是在右边结束的
  • MainAxisAlignment.center:在主轴上居中对齐
  • MainAxisAlignment.spaceBetween:在主轴上,两端对齐,项目之间的间隔都相等。
  • MainAxisAlignment.spaceAround:在主轴上,将多余的控件均匀分布给 子Widget 之间,而且第一个 子Widget 和 最后一个子Widget 距边框的距离是 两个 子Widget 距离的一半
  • MainAxisAlignment.spaceEvenly:在主轴上,将多余的控件均匀分布给 子Widget 之间,而且第一个 子Widget 和 最后一个子Widget 距边框的距离和 子Widget 之间的距离一样

MainAxisSize( 表示主轴应该占用多大的空间)- 2种方式

  • MainAxisSize.min:主轴的大小是能显示完 子Widget 的最小大小,主轴的大小就是 子Widget 的大小
  • MainAxisSize.max:主轴能显示的最大的大小,根据约束来判断

CrossAxisAlignment(表示 子Widget 在交叉轴的对齐方式)-5种方式

  • CrossAxisAlignment.start:沿着交叉轴的起点对齐
    verticalDirection 必须有值,以确定是从左边开始的还是从右边开始的
  • CrossAxisAlignment.end:沿着主轴的终点对齐
    verticalDirection 必须有值,以确定是在左边结束的还是在右边结束的
  • CrossAxisAlignment.center:在交叉轴上居中对齐
  • CrossAxisAlignment.stretch:要求 子Widget 在交叉轴上填满
  • CrossAxisAlignment.baseline:要求 子Widget 的基线在交叉轴上对齐

TextDirection:(子Widget 在主轴方向上的布局顺序)-2种方式

  • TextDirection.rtl:表示从右到左
  • TextDirection.ltr:表示从左到右

VerticalDirection:(子Widget 在交叉轴方向上的布局顺序)-2种方式

  • VerticalDirection.up:表示从下到上
  • VerticalDirection.down:表示从上到下

此处为分割线,到此为止Flex的介绍就结束了

  • 线性布局 - Row(水平方向)和Column(垂直方向)
    线性布局可以将子Widget在同一个方向(水平或者垂直)上排列

Row的使用

效果图


Flutter 学习 - Widget 之 布局 Widget_第3张图片
C7C41AB4-E4FB-4C99-BC4B-12DA4FFE3A1F.png

使用方式:水平方向排列文本和图片

Row(
        children: [
          Text("我是文本"),
          Image.asset(
            "images/timg.jpeg",
            width: 200,
          )
        ],
      )

下面来看下Row的构造方法:

Row({
    Key key,
    MainAxisAlignment mainAxisAlignment = MainAxisAlignment.start,
    MainAxisSize mainAxisSize = MainAxisSize.max,
    CrossAxisAlignment crossAxisAlignment = CrossAxisAlignment.center,
    TextDirection textDirection,
    VerticalDirection verticalDirection = VerticalDirection.down,
    TextBaseline textBaseline,
    List children = const [],
  }) : super(
    ....
  );
}

Column的使用

效果图


Flutter 学习 - Widget 之 布局 Widget_第4张图片
ED19D984-E741-4401-B398-831C5EAFAC8A.png

使用方式:垂直方向排列文本和图片

Column(
        children: [
          Text(
            "我是文本",
            style: TextStyle(fontSize: 24),
          ),
          Image.asset(
            "images/timg.jpeg",
            width: 200,
          )
        ],
      ),

构造函数

Column({
    Key key,
    MainAxisAlignment mainAxisAlignment = MainAxisAlignment.start,
    MainAxisSize mainAxisSize = MainAxisSize.max,
    CrossAxisAlignment crossAxisAlignment = CrossAxisAlignment.center,
    TextDirection textDirection,
    VerticalDirection verticalDirection = VerticalDirection.down,
    TextBaseline textBaseline,
    List children = const [],
  }) : super(
    ...
  );
}

看了Row和Column的构造函数我们可以看出来,跟Flex种的参数是想同的,实际上,它们都继承Flex,其实就是确定了主轴的Flex,所以用法和参数的含义跟Flex的一致,这里就不再进行重复介绍了。

  • 流性布局 - Wrap:页面宽度按照屏幕分辨率适配调整,整体布局不变

Wrap布局会把超楚屏幕显示范围的Widget自动换行,下面看下效果图

Flutter 学习 - Widget 之 布局 Widget_第5张图片
868B8DE6-EA32-4263-8B5C-F28E5E0080E6.png

下面看下Wrap布局的使用方法,上图的主要代码如下

 Wrap(
        children: [
          Text(
            "Hello world " * 100,
            style: TextStyle(fontSize: 20),
          )
        ],
      )

接下来我们看另外一种常用的Wrap布局的显示


Flutter 学习 - Widget 之 布局 Widget_第6张图片
020569D1-8575-4713-97CF-DA1F76FC06CF.png

这种布局对于做Android开发到朋友应该都不陌生,很多带有热门标签的产品都会希望做成这种形式展示,在Flutter使用Wrap就能轻松实现
使用方式:

Wrap(
          direction: Axis.horizontal,
          spacing: 8.0,//主轴方向间距
          runSpacing: 12.0,//交叉轴方向间距
          alignment: WrapAlignment.center,
          runAlignment: WrapAlignment.start,
        children: [
          Chip(
              avatar: CircleAvatar(
                  backgroundColor: Colors.blue,child: Text("A"),
              ),
              label: Text("AAAAAAAAAAAAA"),
          ),Chip(
              avatar: CircleAvatar(
                  backgroundColor: Colors.blue,child: Text("B"),
              ),
              label: Text("BBBBBBBBBBBB"),
          ),Chip(
              avatar: CircleAvatar(
                  backgroundColor: Colors.blue,child: Text("C"),
              ),
              label: Text("CCCCCC"),
          ),Chip(
              avatar: CircleAvatar(
                  backgroundColor: Colors.blue,child: Text("D"),
              ),
              label: Text("DDDDDDDDDDDDDDD"),
          ),Chip(
              avatar: CircleAvatar(
                  backgroundColor: Colors.blue,child: Text("E"),
              ),
              label: Text("EEEEEEEEEEEEEEEEEEEE"),
          )
        ],
      )

下面看下Wrap的构造函数

  Wrap({
    Key key,
    this.direction = Axis.horizontal,//主轴方向,默认水平,类型Axis
    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 children = const [],
  }) : super(key: key, children: children);

其他未介绍的参数跟Flex中的参数意义相同。

  • 层叠布局 - Stack(允许 子Widget 堆叠,子Widget 可以根据到父容器四个边的位置来确定本身的位置)
    Stack是层叠布局,其子Widget会按照添加顺讯确定显示层级,后面添加的会覆盖在前面添加的Widget上面

先看下效果图


Flutter 学习 - Widget 之 布局 Widget_第7张图片
B8B70CA4-9ADE-474B-836E-4FDAD0B702EE.png

使用方式:

Stack(
            children: [
                Image.asset("images/timg.jpeg",),
                Text("Hello Stack",
                style: TextStyle(
                    fontSize: 48,
                    color: Colors.red,
                    backgroundColor: Colors.yellow
                ),)
            ],
        )

Stack的子Widget

为了确定子Widget到容器四个角的位置,Stack将子Widget分为两类
1.positioned子Widget
指被Positioned嵌套起来的Widget,Positioned可以控制子Widget到父容器四个边的距离。
效果图

2.non - positioned子Widget
指不用Positioned嵌套起来的Widget,non-positioned子Widget使用Stack设置的alignment来确定自己在父容器里的位置。

效果图


Flutter 学习 - Widget 之 布局 Widget_第8张图片
E92D7B6A-20F9-40AC-8FBF-EF469FAF25C6.png

实现方式:

Stack(
            fit: StackFit.expand,
            alignment: AlignmentDirectional.bottomEnd,
            children: [
                Positioned(
                    left: 50,
                    top: 100,
                    child: Image.asset("images/timg.jpeg",width: 200,),
                ),
                Text("non-position widget",
                style: TextStyle(
                    fontSize: 48,
                    color: Colors.red,
                    backgroundColor: Colors.yellow
                ),)
            ],
        )

下面是Stack构造函数

Stack({
    Key key,//
    this.alignment = AlignmentDirectional.topStart,//决定子Widget如何对齐
    this.textDirection,//用于确定 alignment 的对齐方向
    this.fit = StackFit.loose,//此参数用于决定 non-positioned子Widget 如何去适应Stack的大小,类型StackFit
    this.overflow = Overflow.clip,//决定如何显示超出 Stack显示空间的 子widget 类型Overflow
    List children = const [],//Stack布局 里排列的内容
  }) : super(key: key, children: children);

StackFit类型-3种方式

  • StackFit.loose:使用 子Widget 自身的大小
  • StackFit.expand:子Widget 扩伸到Stack的大小
  • StackFit.passthrough:Stack的父Widget 的约束无修改的传递给 Stack的子Widget

AlignmentDirectional类型-9种方式

  • AlignmentDirectional.topStart:上边 start 对齐
  • AlignmentDirectional.topCenter:上边 居中 对齐
  • AlignmentDirectional.topEnd:上边 end 对齐
  • AlignmentDirectional.centerStart:中间 start 对齐
  • AlignmentDirectional.center:中间 对齐
  • AlignmentDirectional.centerEnd:中间 end 对齐
  • AlignmentDirectional.bottomStart:下边 start 对齐
  • AlignmentDirectional.bottomCenter:下边 居中 对齐
  • AlignmentDirectional.bottomEnd:下边 end 对齐

Overflow-2种方式(如何显示超出 Stack显示空间的 子widget)

  • Overflow.visible:超出部分仍能看见
  • Overflow.clip:超出部分会被剪裁

Positioned构造函数

Positioned({
    Key key,
    this.left,//离 Stack 左边的距离
    this.top,//离 Stack 上边的距离
    this.right,//离 Stack 右边的距离
    this.bottom,//离 Stack 底边的距离
    this.width,//指定 Widget 的宽度
    this.height,//指定 Widget 的高度
    @required Widget child,//子Widget
  }) : assert(left == null || right == null || width == null),
       assert(top == null || bottom == null || height == null),
       super(key: key, child: child);

关于Flutter中的 布局Widget就介绍完了
以下是我的Flutter系列的链接,后续会持续更新,欢迎大家指正。

Flutter 系列文章

  • Flutter 学习 - 开篇
  • Flutter 学习 - 基础框架
  • Flutter 学习 - 网络请求和数据解析
  • Flutter 学习 - Widget 之 Text
  • Flutter 学习 - Widget 之 RichText
  • Flutter 学习 - Widget 之 Image和Icon
  • Flutter 学习 - Widget 之 TextField
  • Flutter 学习 - Widget 之 菜单按钮
  • Flutter 学习 - Widget 之 布局 Widget
  • Flutter 学习 - 容器类Widget
  • Flutter 学习 - 可滚动的 Widget
  • Flutter 学习 - 功能类Widget

更多关于技术相关的内容请关注博主公众号--迷途程序猿


Flutter 学习 - Widget 之 布局 Widget_第9张图片
迷途程序猿

你可能感兴趣的:(Flutter 学习 - Widget 之 布局 Widget)