【Flutter 布局】001-Flex 布局

【Flutter 布局】001-Flex 布局

一、Flex

1、概述

简介

Flex 是 Flutter 中的一个小部件,用于创建一个弹性布局容器。它允许在一个轴上按比例分配可用空间,并根据需要调整子项的大小。

Flex 小部件有两个重要的属性:directionchildren

  • direction:指定了弹性容器的主轴方向。可以是水平方向(Axis.horizontal)或垂直方向(Axis.vertical)。
  • children:包含在弹性容器中的子项列表。

Flex 使用一种类似于弹性盒子模型的方式来布局子项。子项可以使用 Expanded 小部件来指定它们在弹性容器中的相对比例。通过在子项中使用 Expanded,可以根据需要调整子项的大小,并在弹性容器的主轴上按比例分配可用空间。

构造函数

const Flex({
    super.key,
    required this.direction,
    this.mainAxisAlignment = MainAxisAlignment.start,
    this.mainAxisSize = MainAxisSize.max,
    this.crossAxisAlignment = CrossAxisAlignment.center,
    this.textDirection,
    this.verticalDirection = VerticalDirection.down,
    this.textBaseline,
    this.clipBehavior = Clip.none,
    super.children,
}) : assert(!identical(crossAxisAlignment, CrossAxisAlignment.baseline) || textBaseline != null, 'textBaseline is required if you specify the crossAxisAlignment with CrossAxisAlignment.baseline');

2、基本使用

代码示例

Container(
    color: Colors.white,
    child: Flex(
        direction: Axis.horizontal,
        children: [
            Container(color: Colors.red, width: 300, height: 300, child: const Text('Hello World')),
            Container(color: Colors.blue, width: 300, height: 300, child: const Text('Hello World')),
            Container(color: Colors.green, width: 300, height: 300, child: const Text('Hello World')),
        ],
    )

运行结果

image-20230611122948523

3、方向

取值范围

Axis 是一个枚举类型,用于表示二维空间中的两个基本方向。

以下是 Axis 的两个取值及其含义:

  • horizontal:水平方向,表示从左到右的方向。
  • vertical:垂直方向,表示从上到下的方向。

代码示例

参考主轴对齐方式

4、水平方向:主轴对齐方式

取值范围

MainAxisAlignment 是一个枚举类型,用于指定在 Flex 布局中子级容器沿主轴(main axis)的对齐方式。

以下是 MainAxisAlignment 的各个取值及其含义:

  • start:尽可能靠近主轴的起始位置放置子级容器。
  • end:尽可能靠近主轴的结束位置放置子级容器。
  • center:将子级容器放置在主轴的中间位置。
  • spaceBetween:在子级容器之间均匀分布剩余空间。
  • spaceAround:在子级容器之间均匀分布剩余空间,并在第一个和最后一个子级容器之前及之后分配剩余空间的一半。
  • spaceEvenly:在子级容器之间均匀分布剩余空间,并在第一个和最后一个子级容器之前及之后分配相等的剩余空间。

代码示例

Container(
    color: Colors.white,
    child: Flex(
        direction: Axis.horizontal,
        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
        children: [
            Container(color: Colors.red, width: 300, height: 300, child: const Text('Hello World')),
            Container(color: Colors.blue, width: 300, height: 300, child: const Text('Hello World')),
            Container(color: Colors.green, width: 300, height: 300, child: const Text('Hello World')),
        ],
    ),
)

运行结果

image-20230611124548242

5、垂直方向:主轴对齐方式

代码示例

Container(
    color: Colors.white,
    child: Flex(
        direction: Axis.vertical,
        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
        children: [
            Container(color: Colors.red, width: 100, height: 100, child: const Text('Hello World')),
            Container(color: Colors.blue, width: 100, height: 100, child: const Text('Hello World')),
            Container(color: Colors.green, width: 100, height: 100, child: const Text('Hello World')),
        ],
    ),
)

运行结果

image-20230611124732231

6、主轴尺寸

取值范围

MainAxisSize 是一个枚举类型,用于控制在主轴上子级容器应该占据多少空间。

在进行 Flex 布局时,沿主轴的可用空间会被分配给子级容器。在分配空间后,可能会有一些剩余的空闲空间。MainAxisSize 控制是否最大化或最小化空闲空间的量,同时受到传入的布局约束的限制。

以下是 MainAxisSize 的两个取值及其含义:

  • min最小化主轴上的空闲空间的量,受传入的布局约束的限制。如果传入的布局约束的 BoxConstraints.minWidthBoxConstraints.minHeight 足够大,可能仍会有非零的空闲空间。如果传入的布局约束是无界的,并且任何子级容器具有非零的 FlexParentData.flex 值和 FlexFit.tight 的适应方式(由 Expanded 应用),则 RenderFlex 将断言,因为会存在无限剩余的空闲空间,而不能给予盒子无限的大小。
  • max最大化主轴上的空闲空间的量,受传入的布局约束的限制。如果传入的布局约束的 BoxConstraints.maxWidthBoxConstraints.maxHeight 足够小,可能仍然没有空闲空间。如果传入的布局约束是无界的,RenderFlex 将断言,因为会存在无限剩余的空闲空间,而不能给予盒子无限的大小。

代码示例:MainAxisSize.max

Container(
    color: Colors.white,
    child: Flex(
        direction: Axis.horizontal,
        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
        mainAxisSize: MainAxisSize.max,
        children: [
            Container(color: Colors.red, width: 300, height: 300, child: const Text('Hello World')),
            Container(color: Colors.blue, width: 300, height: 300, child: const Text('Hello World')),
            Container(color: Colors.green, width: 300, height: 300, child: const Text('Hello World')),
        ],
    ),
)

运行结果

image-20230611125337499

代码示例:MainAxisSize.min

Container(
    color: Colors.white,
    child: Flex(
        direction: Axis.horizontal,
        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
        mainAxisSize: MainAxisSize.min,
        children: [
            Container(color: Colors.red, width: 300, height: 300, child: const Text('Hello World')),
            Container(color: Colors.blue, width: 300, height: 300, child: const Text('Hello World')),
            Container(color: Colors.green, width: 300, height: 300, child: const Text('Hello World')),
        ],
    )

运行结果

image-20230611125433412

7、交叉轴对其方式

交叉轴意思就是对应轴,主轴是水平方向,交叉轴就是垂直方向,反之亦然!

取值范围

CrossAxisAlignment 是一个枚举类型,用于确定在 Flex 布局中子级容器沿交叉轴的对齐方式。

以下是 CrossAxisAlignment 的取值及其含义:

  • start:将子级容器的起始边与交叉轴的起始边对齐。例如,在一个垂直方向(具有垂直轴)的列(Column)中,如果文本方向为从左到右(TextDirection.ltr),则子级容器的左边将与列的左边对齐。如果在水平方向使用此值,则需要提供 TextDirection 来确定起始边是左边还是右边。如果在垂直方向使用此值,则需要提供 VerticalDirection 来确定起始边是顶部还是底部。
  • end:尽可能地将子级容器与交叉轴的末端对齐。例如,在一个垂直方向(具有垂直轴)的列(Column)中,如果文本方向为从左到右(TextDirection.ltr),则子级容器的右边将与列的右边对齐。如果在水平方向使用此值,则需要提供 TextDirection 来确定末端是左边还是右边。如果在垂直方向使用此值,则需要提供 VerticalDirection 来确定末端是顶部还是底部。
  • center:将子级容器的中心与交叉轴的中心对齐。这是默认的交叉轴对齐方式。
  • stretch:要求子级容器填充交叉轴。这会导致传递给子级容器的约束在交叉轴上变为紧密约束。
  • baseline:将子级容器沿交叉轴以使其基线对齐。由于基线始终是水平的,所以该对齐方式适用于水平的主轴。如果主轴是垂直的,则此值会被视为 start。对于水平的主轴,如果传递给 Flex 布局的最小高度约束超过了交叉轴的内在高度,子级容器将尽可能靠近顶部对齐,同时保持基线对齐。换句话说,额外的空间将位于所有子级容器的下方。没有基线的子级容器将与顶部对齐。

水平方向:代码示例:CrossAxisAlignment.center

Container(
    color: Colors.white,
    child: Flex(
        direction: Axis.horizontal,
        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
        mainAxisSize: MainAxisSize.max,
        crossAxisAlignment: CrossAxisAlignment.center,
        children: [
            Container(color: Colors.red, width: 300, height: 300, child: const Text('Hello World')),
            Container(color: Colors.blue, width: 200, height: 200, child: const Text('Hello World')),
            Container(color: Colors.green, width: 300, height: 300, child: const Text('Hello World')),
        ],
    ),
)

运行结果

image-20230611125825234

垂直方向:代码示例:CrossAxisAlignment.center

Container(
    color: Colors.white,
    child: Flex(
        direction: Axis.vertical,
        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
        mainAxisSize: MainAxisSize.max,
        crossAxisAlignment: CrossAxisAlignment.center,
        children: [
            Container(color: Colors.red, width: 200, height: 200, child: const Text('Hello World')),
            Container(color: Colors.blue, width: 100, height: 100, child: const Text('Hello World')),
            Container(color: Colors.green, width: 200, height: 200, child: const Text('Hello World')),
        ],
    ),
)

运行结果

image-20230611125957767

8、水平方向:子项顺序

取值范围

TextDirection 是一个枚举类型,用于表示文本的方向。

以下是 TextDirection 的取值及其含义:

  • rtl:文本从右到左流动,例如阿拉伯语、希伯来语等。
  • ltr:文本从左到右流动,例如英语、法语等。

代码示例

Container(
    color: Colors.white,
    child: Flex(
        direction: Axis.horizontal,
        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
        mainAxisSize: MainAxisSize.max,
        crossAxisAlignment: CrossAxisAlignment.center,
        textDirection: TextDirection.rtl,
        children: [
            Container(color: Colors.red, width: 300, height: 300, child: const Text('Hello World')),
            Container(color: Colors.blue, width: 200, height: 200, child: const Text('Hello World')),
            Container(color: Colors.green, width: 300, height: 300, child: const Text('Hello World')),
        ],
    ),
)

运行结果

image-20230611130453910

9、垂直方向:子项顺序

取值范围

VerticalDirection 是一个枚举类型,用于确定垂直方向上的方向。

以下是 VerticalDirection 的取值及其含义:

  • up:子级容器应从底部开始,并沿垂直方向堆叠到顶部。在此情况下,“start” 在底部,“end” 在顶部。
  • down:子级容器应从顶部开始,并沿垂直方向堆叠到底部。在此情况下,“start” 在顶部,“end” 在底部。

代码示例

Container(
    color: Colors.white,
    child: Flex(
        direction: Axis.vertical,
        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
        mainAxisSize: MainAxisSize.max,
        crossAxisAlignment: CrossAxisAlignment.center,
        verticalDirection: VerticalDirection.up,
        children: [
            Container(color: Colors.red, width: 200, height: 200, child: const Text('Hello World')),
            Container(color: Colors.blue, width: 150, height: 150, child: const Text('Hello World')),
            Container(color: Colors.green, width: 200, height: 200, child: const Text('Hello World')),
        ],
    ),
)

运行结果

image-20230611130847259

10、文本基线

取值范围

TextBaseline 是一个枚举类型,用于指定文本对齐时使用的水平线。

以下是 TextBaseline 的取值及其含义:

  • alphabetic:用于对齐字母字符底部的水平线。
  • ideographic:用于对齐表意字符的水平线。

代码示例

两个取值暂未看出明显区别,暂不做深究!

Container(
    color: Colors.white,
    child: const Flex(
        direction: Axis.horizontal,
        mainAxisAlignment: MainAxisAlignment.center,
        crossAxisAlignment: CrossAxisAlignment.baseline,
        textBaseline: TextBaseline.alphabetic,
        children: [
            Text('Hello World,Hello World,Hello World,\r\nHello World,Hello World,Hello World', style: TextStyle(fontSize: 50)),
            Text('訾博', style: TextStyle(fontSize: 30)),
        ],
    ),
)

运行结果

image-20230611132218749

11、剪辑行为

取值范围

枚举类型 Clip 是用于指定小部件内容剪辑方式的选项。

以下是 Clip 的取值及其含义:

  • none:没有剪辑。这是大多数小部件的默认选项。如果内容没有超出小部件的边界,不会进行任何剪辑,也不会产生性能开销。如果内容超出边界,则需要显式指定其他的剪辑选项。
  • hardEdge:剪辑内容,但不应用反锯齿。这种方式会导致剪辑边缘呈锯齿状,适用于容器为轴对齐矩形或轴对齐圆角矩形且圆角半径非常小的情况。比起其他剪辑模式,速度较快但比 none 模式慢。
  • antiAlias:剪辑内容并应用反锯齿。这种方式会使剪辑边缘呈现平滑的外观。速度比 antiAliasWithSaveLayer 快,但比 hardEdge 模式慢。在处理圆形和弧形时常用的方式。
  • antiAliasWithSaveLayer:剪辑内容并应用反锯齿,同时在剪辑后立即创建一个离屏缓冲区。所有后续绘制操作都在该缓冲区上进行,最后再进行剪辑和合成。这种方式非常慢,但与 antiAlias 不同,它会引入一个离屏缓冲区,改变了绘制的语义。这种方式很少使用,仅在特定情况下才需要,例如在图像上叠加不同背景颜色时。如果可以避免在同一位置叠加多个颜色(例如只在图像缺失的地方使用背景颜色),则使用 antiAlias 模式会更快速。

代码示例

代码示例看不出特别效果,暂不做深究。

二、Row

1、概述

简介

Row = Flex + direction: Axis.horizontal

源代码

class Row extends Flex {
  const Row({
    super.key,
    super.mainAxisAlignment,
    super.mainAxisSize,
    super.crossAxisAlignment,
    super.textDirection,
    super.verticalDirection,
    super.textBaseline,
    super.children,
  }) : super(
    direction: Axis.horizontal,
  );
}

2、基本使用

代码示例

Container(
    color: Colors.white,
    child: Row(
        children: [
            Container(color: Colors.red, width: 300, height: 300, child: const Text('Hello World')),
            Container(color: Colors.blue, width: 300, height: 300, child: const Text('Hello World')),
            Container(color: Colors.green, width: 300, height: 300, child: const Text('Hello World')),
        ],
    ),
)

运行结果

image-20230611122948523

三、Column

1、概述

简介

Column = Flex + direction: Axis.vertical

源代码

class Column extends Flex {
  const Column({
    super.key,
    super.mainAxisAlignment,
    super.mainAxisSize,
    super.crossAxisAlignment,
    super.textDirection,
    super.verticalDirection,
    super.textBaseline,
    super.children,
  }) : super(
    direction: Axis.vertical,
  );
}

2、基本使用

代码示例

Container(
    color: Colors.white,
    child: Column(
        children: [
            Container(color: Colors.red, width: 200, height: 200, child: const Text('Hello World', style: TextStyle(fontSize: 40))),
            Container(color: Colors.blue, width: 150, height: 150, child: const Text('Hello World', style: TextStyle(fontSize: 40))),
            Container(color: Colors.green, width: 200, height: 200, child: const Text('Hello World', style: TextStyle(fontSize: 40))),
        ],
    ),
)

运行结果

image-20230611133320679

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Flutter中的Flex布局是一种弹性布局模型,它可以让子元素按照一定的比例分配父容器的可用空间。Flex布局主要包含三个组件:FlexFlexible和Expanded。 1. Flex Flex是一个容器组件,它可以将子组件按照一定的比例排列。Flex有两个属性:direction和mainAxisAlignment,其中direction表示子组件排列的方向,默认为水平方向,mainAxisAlignment表示子组件在主轴上的对齐方式。 2. Flexible Flexible是一个伸缩组件,它可以根据父容器的可用空间来调整自身的尺寸。Flexible有三个属性:flex、fit和child,其中flex表示子组件的比例,fit表示子组件在可用空间不足时的适应方式,child表示子组件。 3. Expanded Expanded是Flexible的一种特殊情况,它的flex属性默认为1。使用Expanded可以让子组件占据父容器剩余的所有空间。 下面是一个简单的Flex布局示例: ``` Flex( direction: Axis.horizontal, mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ Flexible( flex: 1, fit: FlexFit.tight, child: Container( height: 50, color: Colors.red, ), ), Flexible( flex: 2, fit: FlexFit.loose, child: Container( height: 50, color: Colors.blue, ), ), Expanded( child: Container( height: 50, color: Colors.green, ), ), ], ) ``` 在这个示例中,我们创建了一个水平方向的Flex容器,其中有三个子组件。第一个子组件使用了Flexible,它的flex属性为1,表示占据1/3的空间;第二个子组件也使用了Flexible,它的flex属性为2,表示占据2/3的空间;第三个子组件使用了Expanded,它会占据剩余的所有空间。在这个示例中,第一个子组件使用了tight适应方式,它会尽可能地占据可用空间;第二个子组件使用了loose适应方式,它会根据自身的尺寸来调整大小。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值