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

Posted

技术标签:

【中文标题】为啥 SizedBox 的存在会移动 Stack 中的兄弟姐妹?【英文标题】:Why is the presence of a SizedBox moves the siblings in a Stack?为什么 SizedBox 的存在会移动 Stack 中的兄弟姐妹? 【发布时间】:2022-01-24 02:14:17 【问题描述】:

我正在为 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),

【问题讨论】:

发布最小的、可重现的代码示例(没有任何外部依赖项)以显示您的问题 @pskink 在那里找到最小的前任dartpad.dev/?id=ccd214b1efacb61b158f6f0c2092e809 试试fit: StackFit.expand - 默认是loose @pskink 唉,延伸了整个小部件 【参考方案1】:

我终于找到了一个解决方案,它包括使用 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)),



【讨论】:

以上是关于为啥 SizedBox 的存在会移动 Stack 中的兄弟姐妹?的主要内容,如果未能解决你的问题,请参考以下文章

有没有办法获取现有小部件的大小?

为啥要使用 Deque 而不是内置 Stack<>? [复制]

为啥要使用 Deque 而不是内置 Stack<>? [复制]

GestureDedector 的 onTap 事件不适用于 Sizedbox

Flutter中常用的组件-SizedBox

Flutter ListView.builder sizedbox问题