为什么 SizedBox 的存在会移动 Stack 中的兄弟姐妹?

Why is the presence of a SizedBox moves the siblings in a Stack?

我正在为 Flutter 处理 Widget 定位的方式而苦恼。

上下文:我的目标是布置一个带有移动车辆和加油泵的动画场景;根据设备方向,我想缩放和定位观看者的眼睛(泵位置)在屏幕的中心,就像我在 iPhone 上使用原生 Swift 版本一样如下:

横向模式:

人像模式:

在尝试使用 Flutter 实现此目的时,我遇到了各种问题,其中一个是调试小部件的存在将其他小部件从同一堆栈中移出:

它以堆栈中的 SizedBox 为中心…

但没有它就不行了:

我的代码如下,可以在此处找到最小的 darted 版本:https://dartpad.dev/?id=ccd214b1efacb61b158f6f0c2092e809


Widget buildScene(Size size, /* double scale,*/ bool debug) {
    final hill = Hill(size: size);

    final punmpOffsetX = size.width / 4;

    // == Build the scene
    return Stack(clipBehavior: Clip.none, children: [
      // == The whole scene debug materialisation 
      if (debug). => THIS IS WHAT I TOGGLE WHICH MOVES THE REST OF THE SCENE
      SizedBox(
          width: size.width,
          height: size.height,
          child: Container(
            color: const Color(0x7ff67e22),
          )),

      // == Add the sky
      ...widget.clouds,

      // == Add ground
      hill,

      // == The pump
      Transform.translate(
          offset: Offset(punmpOffsetX /*- 115 / 2*/, 120),
          child: Container(
              width: 150,
              child: ScaleTransition(
                  scale: Tween<double>(begin: 3, end: 1).animate(
                      CurvedAnimation(
                          parent: _controller, curve: Curves.elasticOut)),
                  child: Pump(offset: Offset.zero, width: 150)))),

      // == The animated vehicle
      DrivingVehicle(hill: hill),

我终于找到了一个解决方案,它包括使用 Positioned() Widget 来绝对定位 Widget。 Transform.translate 向渲染流中的小部件当前位置添加平移,这就是为什么删除小部件会使其余小部件移动的原因。

代码变为:


    // == Build the scene
    return Stack(clipBehavior: Clip.none, children: [
      // == The whole scene debug materialisation 
      if (debug)
      Positioned(left: 0, top: 0, child: SizedBox(
          width: size.width,
          height: size.height,
          child: Container(
            color: const Color(0x7ff67e22),
          ))),

    
      // == Add ground
      Positioned(left: 0, top: 0, child: hill),

      // == The pump
      Positioned(left: punmpOffsetX, top: 120, child: 
          offset: Offset(punmpOffsetX /*- 115 / 2*/, 120),
          child: Container(
              width: 150,
              child: ScaleTransition(
                  scale: Tween<double>(begin: 3, end: 1).animate(
                      CurvedAnimation(
                          parent: _controller, curve: Curves.elasticOut)),
                  child: Pump(offset: Offset.zero, width: 150)))),

      // == The animated vehicle
      Positioned(left: 0, top: 0, child: DrivingVehicle(hill: hill)),