likes
comments
collection
share

搞懂Flutter的布局约束

作者站长头像
站长
· 阅读数 64

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,
      ),
    );
  }
}
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的约束考虑进去.

转载自:https://juejin.cn/post/7217770698784555064
评论
请登录