flutter - Flutter中使用child center的stack child的相对定位

标签 flutter dart

我的布局的一部分显示了一个图像,上面有对象。图像和对象位于 Stack 中。对于物体位置,我知道物体中心相对于图像的相对坐标。例如 (0,0) 表示对象中心应位于图像的左上角,(0.23,0.7) 表示“中心位于宽度的 23% 和高度的 70%”。我知道对象的大小,但我不知道将分配给图像的先验大小。

我尝试为此使用 Align 但它不使用对象的中心:例如 AlignAlignment(1,1)将对象的右下角放在右下角。然后我尝试添加一个变换以将对象的中心转换为 (0,0),但这仅适用于右下角,例如,当使用 Alignment(0,0) 在中心对齐时,位置是错误的)

我想到了使用Positioned 小部件,但是我无法在build 函数中知道图像大小。

如何正确定位我的对象?在下面的例子中,我怎样才能得到以绿色矩形右下角为中心的红色圆圈? (以一种也适用于其他坐标的方式)

class Test extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Row(
        children: <Widget>[
          Expanded(
            child: Column(
              children: <Widget>[
                Expanded(
                  child: Container(
                    color: Colors.blue,
                    child: Stack(
                      alignment: Alignment.center,
                      children: [
                        AspectRatio(
                          aspectRatio: 1.5,
                          child: Container(
                            color: Colors.green,
                          ),
                        ),
                        Align(
                          alignment: Alignment(1,
                              1), // Should put circle center on bottom-right corner
                          child: Container(
                            width: 100,
                            height: 100,
                            // transform: Matrix4.translationValues(50, 50, 0), // doesn't work except for bottom-right corner
                            decoration: BoxDecoration(
                              color: Colors.red,
                              shape: BoxShape.circle,
                            ),
                          ),
                        )
                      ],
                    ),
                  ),
                ),
                Text('Bottom widget'),
              ],
            ),
          ),
          Text('Right widget'),
        ],
      ),
    );
  }
}

最佳答案

这是 pskink 建议的基于 CustomMultichildLayout 的解决方案:

enum _Slot {
  image,
  circle,
}

class MyDelegate extends MultiChildLayoutDelegate {
  final FractionalOffset objectCenter;

  MyDelegate({@required this.objectCenter});

  @override
  void performLayout(Size size) {
    Size imageSize = Size.zero;
    Offset imagePos = Offset.zero;

    if (hasChild(_Slot.image)) {
      imageSize = layoutChild(_Slot.image, BoxConstraints.loose(size));

      // Center the image in the available space
      imagePos = (size - imageSize as Offset) * 0.5;
      positionChild(_Slot.image, imagePos);
    }

    if (hasChild(_Slot.circle)) {
      Size childSize = layoutChild(_Slot.circle, BoxConstraints());
      positionChild(
          _Slot.circle,
          imagePos +
              objectCenter.alongSize(imageSize) -
              childSize.center(Offset.zero));
    }
  }

  @override
  bool shouldRelayout(MultiChildLayoutDelegate oldDelegate) => false;
}

class Test extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Row(
        children: <Widget>[
          Expanded(
            child: Column(
              children: <Widget>[
                Expanded(
                  child: Container(
                    color: Colors.blue,
                    child: Center(
                      child: CustomMultiChildLayout(
                        delegate:
                            MyDelegate(objectCenter: FractionalOffset(1, 1)),
                        children: [
                          LayoutId(
                            id: _Slot.image,
                            // Use AspectRatio to emulate an image
                            child: AspectRatio(
                              aspectRatio: 1.5,
                              child: Container(
                                color: Colors.green,
                              ),
                            ),
                          ),
                          LayoutId(
                            id: _Slot.circle,
                            child: Container(
                              width: 100,
                              height: 100,
                              decoration: BoxDecoration(
                                color: Colors.red,
                                shape: BoxShape.circle,
                              ),
                            ),
                          )
                        ],
                      ),
                    ),
                  ),
                ),
                Text('Bottom widget'),
              ],
            ),
          ),
          Text('Right widget'),
        ],
      ),
    );
  }
}

传递给委托(delegate)的偏移量可以是任何相对坐标。在上面的示例中,我传递了 (1,1),因此红色圆圈位于右下角的中心:

enter image description here

关于flutter - Flutter中使用child center的stack child的相对定位,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56644551/

相关文章:

webview - Flutter WebviewPlugin 去除网站的页眉和页脚

flutter - Flutter-TextField验证无效

android - 背景类似于 Flutter 中的 Container

flutter - 验证器错误消息更改了 TextFormField 的高度

dart - 在 Flutter 中检索图像路由

flutter - 在 Flutter 中创建对齐文本的网格/表格

flutter - 如何在 Flutter 中更改 CupertinoNavigationBar 中后退按钮的颜色

flutter - Flutter标签-即使未显示标签,也会创建一个标签

flutter - 超过6个ProxyProvider的提供者,如何?

html - Dart如何创建模式页面?