如何将小部件放置在具有比例大小和位置的小部件上方

How to place a Widget above a widget with proportional size and position

我想要一组小部件按比例放置在背景小部件(图像小部件)上方。

我尝试了以下方法。 创建了一个 Widget 数组并将其添加到 Stack 使用 LayoutBuilder 构建子部件并使用 Positioned 部件定位它们。

但由于 Incorrect use of ParentDataWidget. 错误,它没有工作。

Widget build(BuildContext context) {
    final _widgetStack = <Widget>[];
    _widgetStack.add(Container(
      child: Image.network(
          'https://nikhileshwar96.github.io/Showcase/blue.jpg'),
      color: Color.fromARGB(255, 255, 255, 255),
    ));
    for (int _i = 1; _i < 5; _i++) {
      _widgetStack.add(LayoutBuilder(
          builder: (context, constrain) => Positioned(
                top: constrain.maxWidth * 0.5,
                left: constrain.maxHeight * 0.5,
                width: constrain.maxWidth * 0.25,
                height: constrain.maxHeight * 0.25,
                child: Container(
                  child: Text('HiTHERE'),
                  color: Color.fromARGB(255, 255, 0, 0),
                ),
              )));
    }

    return Container(
      child: Scaffold(
        appBar: AppBar(
          title: Text("Hi there"),
        ),
        body: 
          Container(
            height: 500,
            child: Stack(
              children: _widgetStack,
            ),
          )
      ),
    );
  }

根据文档 here:

A Positioned widget must be a descendant of a Stack, and the path from the Positioned widget to its enclosing Stack must contain only StatelessWidgets or StatefulWidgets (not other kinds of widgets, like RenderObjectWidgets).

解决您的问题: 您可以使用 Transform 小部件的 Transform.translate 构造函数代替 Positioned 小部件。所以你的代码看起来像这样:

for (int _i = 1; _i < 5; _i++) {
 _widgetStack.add(LayoutBuilder(
          builder: (context, constrain) {
            return Transform.translate(
            offset: Offset(constrain.maxWidth * 0.5, constrain.maxHeight * 0.5),
            child: Container(
              width: constrain.maxWidth * 0.25,
              height: constrain.maxHeight * 0.25,
              child: Text('HiTHERE'),
              color: Color.fromARGB(255, 255, 0, 0),
            ),
          );
          }));
    }

尝试:

child: CustomMultiChildLayout(
  delegate: FooDelegate([
    Rect.fromLTWH(0, 0, 1, 1),
    Rect.fromLTWH(0.1, 0.1, 0.2, 0.05),
    Rect.fromLTWH(0.5, 0.1, 0.2, 0.05),
  ]),
  children: [
    LayoutId(id: 0, child: Container(color: Colors.grey)),
    LayoutId(id: 1, child: Material(color: Colors.red, child: InkWell(onTap: () {},))),
    LayoutId(id: 2, child: Material(color: Colors.blue, child: InkWell(onTap: () {},))),
  ],
)

自定义 MultiChildLayoutDelegate 可能看起来像(但是如何实现委托完全取决于您):

class FooDelegate extends MultiChildLayoutDelegate {
  final List<Rect> rects;

  FooDelegate(this.rects);

  @override
  void performLayout(Size size) {
    var id = 0;
    for (var rect in rects) {
      var childRect = Rect.fromLTWH(
        size.width * rect.left,
        size.height * rect.top,
        size.width * rect.width,
        size.height * rect.height);
      print('$childRect $size');
      positionChild(id, childRect.topLeft);
      layoutChild(id, BoxConstraints.tight(childRect.size));
      id++;
    }
  }

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