Flutter布局通常会呈现一些奇怪的现象,例如,我期望一个Container是100宽高的正方形,于是我这样写

void main() => runApp(Home());
class Home extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.amber,
      width: 100,
      height: 100,
    );
  }
}

可是成果却是全屏.

搞懂Flutter的布局约束
感觉难以了解,呈现这种情况的原因是,Flutter布局方法是对Widget Tree先进行自上而下对每个Widget进行束缚(Constraint 过程),再自下而上决议每个Widget的巨细(Size 过程),最终由父Widget决议每个子Widget的方位.总结下来就三步

  • 1,向下Constraint

  • 2,向上Size

  • 3,父Widget决议方位

这儿咱们来解释一下上面的代码为什么会白屏. 在第一步过程中屏幕是Container的父亲,屏幕给Container的束缚是和屏幕相同大,在向上Size的过程中,这儿咱们有必要了解的是,不是子Widget想多大就多大,它有必要考虑它的束缚后给出一个巨细,这儿虽然它是宽100,高100不过束缚强制它全屏了,所以向上Size的时分它便是全屏巨细,最终父亲也便是屏幕决议它的方位,也便是坐标(0,0).

咱们改一下代码

void main() => runApp(Home());
class Home extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(
      child: Container(
        color: Colors.amber,
        width: 100,
        height: 100,
      ),
    );
  }
}

现在咱们对Container包裹了一个Center,运行后是

搞懂Flutter的布局约束

现在和咱们期望的姿态相同了,因为现在的Center关于它子Widget的束缚不是屏幕巨细了,而是子Widget它期望自己多大就多大,最终Center决议Container的方位是居中,这样就看到了运行后的作用了。

这儿可能会有个疑问是,为什么屏幕关于子Widget的束缚是全屏幕巨细,而Center关于它子Widget的束缚却是它期望多大就多大呢?我怎样知道一个父Widget的是怎样束缚子Widget的呢?

关于屏幕它是作为一个最上层的父亲,它给予第一个Widget(根Widget)的束缚便是屏幕巨细,不管根Widget怎样设置自己巨细都授全屏束缚。接下来Widget的束缚便是依据详细情况详细定了(视Widget类型,剩下空间等影响,详细情况详细剖析)

下面咱们再来一个比如

void main() => runApp(Home());
class Home extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      child: Container(
        color: Colors.amber,
        width: 100,
        height: 100,
      ),
    );
  }
}

运行后变成这样

搞懂Flutter的布局约束
又是全屏了,这儿证明了Container关于子Widget束缚是撑满的. 那么我不想撑满,除了之前说到的Center还有哪些方法呢? 1,运用Align Align能够用来对齐一个Widget,同时它对子Widget的巨细束缚是子widget想多大就多大.(当然这儿还需要满足Align父亲的束缚).

void main() => runApp(Home());
class Home extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Align(
      alignment: Alignment.centerLeft,
      child: Container(
        color: Colors.amber,
        width: 100,
        height: 100,
      ),
    );
  }
}

搞懂Flutter的布局约束
2,运用Stack

void main() => runApp(Home());
class Home extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Stack(
      textDirection: TextDirection.ltr,
      children: [
        Container(
          color: Colors.amber,
          width: 100,
          height: 100,
        )
      ],
    );
  }
}

搞懂Flutter的布局约束

当然还有其它Widget是对子Widget的巨细束缚是子widget想多大就多大,详细这儿就不一一列举了.

最终再来看一个Colum的比如,回忆下布局束缚的整个流程.

void main() => runApp(Home());
class Home extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Container(
          color: Colors.amber,
          width: 100,
          height: 100,
        ),
        Container(
          color: Colors.red,
          width: 100,
          height: 100,
        ),
        Container(
          color: Colors.blue,
          width: 100,
          height: 100,
        ),
      ],
    );
  }
}

搞懂Flutter的布局约束

咱们来剖析一遍

1,Column作为第一个Widget,自然是全屏.

2,在Column束缚下,三个Container需要100的宽高,Column都能满足它们的要求

3,依据Column的布局特性决议三个Container的方位.

结语:

Flutter中Widget不能决议它自己的巨细和方位,有必要要结合父Widget的束缚去决议,相同父Widget也有父Widget,所以咱们在指定Widget的方位和巨细的时分一定要把父Widget的束缚考虑进去.