flutter 溢出七种布局方案

3,744 阅读3分钟

本文和大家一起讨论下溢出效果的七种实现方案。

让我们来看一个效果。蓝色区块溢出红色区块,延伸到上方。

image.png

方案一 SizedOverflowBox

要实现这样的效果很容易想到的就是 SizedOverflowBox,复制下面的代码到 main.dart,运行后查看效果。

Container(
   color: Colors.green[400],
   width: 100,
   height: 100,
   alignment: Alignment.topCenter,
   child: SizedOverflowBox(
     size: Size.zero,
     child:
         Container(color: Colors.blue, width: 50, height: 50),
   )))));

SizedOverflowBox 默认 会把 child 摆放在中间,所以就用了溢出一半的效果。

SizedOverflowBox 会透传 约束给 child,SizedOverflowBox 的 约束 必须是 loose,否则无法让 child 溢出。因为如果是 tight 约束 SizedOverflowBox 和 child 一样大了。

方案二 OverflowBox

实现了同样的效果,但不 SizedOverflowBox 简洁。

Container(
      color: Colors.green[400],
      width: 100,
      height: 100,
      child: OverflowBox(
        maxHeight: 150,
        child:Align(
          alignment: Alignment.topCenter,
          child:
           Container(color: Colors.blue, width: 50, height: 50))
      ))

OverflowBox 会在父级允许的范围内尽可能的大。在本例中 OverflowBox 的大小为 size(100,100)

布局解说

  1. OverflowBox 会充满绿色 container,并允许 child 可以达到 150 height
  2. Align 高度 150,OverflowBox 默认居中摆放 Align,向上溢出 25,向下溢出 25。
  3. Align 顶部分摆放 blue Container,效果上正好向上溢出 25。

方案三 stack

虽然在效果是一样的,但 stack 的本意是层叠。和 web 中 绝对定位差不多。

Stack(
   clipBehavior: Clip.none,
   alignment: Alignment.center,
   children: [
    Container( 
      color: Colors.green[400],
      width: 100,
      height: 100,),
      Positioned(
      top:-25,
      child: Container(color: Colors.blue, width: 50, height: 50))
    ]
)

布局解说

  1. stack 和 green container 一样大。
  2. stack 根据 top:-25 ,确定上下位置,再根据 alignment: Alignment.center,确定左右位置,clipBehavior: Clip.none 允许溢出,最终效果就是左右居中,向上溢出 25。

stack 在只有 positioned 定位元素的情况下无尽量大。在本例中受到的是父级的 loose 约束,最终 size(100,100

Positioned left:0,right:0,相当于指定了 Positioned 宽度 100%,并传一个 tight 约束给 Align, Align把 tight约束转化为 loose 约束,蓝色container 最终 宽度 50,左右居中。因为 stack设置为 允许溢出,所以高度显示为 200。

方案四 transform

Container(
    color: Colors.green[400],
    width: 100,
    height: 100,
    alignment:Alignment.topCenter,
    child:Transform.translate(
      offset:const Offset(0,-25),
      child:
         Container(color: Colors.blue, width: 50, height: 50))
)

方案五 FitteBbox

 Container(
    color: Colors.green[400],
    width: 100,
    height: 100,
    child:FittedBox(
      fit: BoxFit.none,
      child:Container(
        alignment: Alignment.topCenter,
         height: 150,
         child:Container(color: Colors.blue, width: 50, height: 50)))
    )

布局解说

  1. FittedBox 放飞 child ,高度 150
  2. FittedBox 默认居中摆放 child ,向上溢出 25。
  3. FittedBox' child 在顶部居中 blue container ,最终效果就是向上溢出 20,左右居中。

方案六 Align

Container(
      color: Colors.green[400],
      width: 100,
      height: 100,
      alignment: Alignment(0, -2),
      child: Container(color: Colors.blue, width: 50, height: 50),
)

这不用解说了,这应该是最简单的方案了。如果对 Alignment 不熟悉可以看这里 Flutter Align 详解

方案七 CustomSingleChildLayout

用 CustomSingleChildLayout 是肯定可以的,因为它的灵活性是最大的。如果有兴趣点这里看 详情

总结了这些多溢出的方案,也是为了让大家了解一下,哪些组件可以溢出,就这样的能力,等遇到问题的时候,会第一时间想起来。

其实还有很多组件可以有溢出的效果,如果都算上的话,远不止 7 种。比如 BaseLineFractionalTranslation 等。