【问题标题】:How to place a Widget above a widget with proportional size and position如何将小部件放置在具有成比例大小和位置的小部件上方
【发布时间】:2021-02-07 04:15:29
【问题描述】:

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

我尝试了以下方法。 创建了一个 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,
            ),
          )
      ),
    );
  }

【问题讨论】:

    标签: flutter dart widget flutter-layout


    【解决方案1】:

    根据文档here

    定位小部件必须是堆栈的后代,并且路径从 定位到其封闭堆栈的小部件必须仅包含 StatelessWidgets 或 StatefulWidgets(不是其他类型的小部件,例如 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),
                ),
              );
              }));
        }
    

    【讨论】:

    • 谢谢,您的回答很好。但是使用 Transform gesture issue 的手势存在问题。我会为其他选项保持打开状态。
    • 也可以考虑一个 FittedBox。
    【解决方案2】:

    尝试:

    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;
    }
    

    【讨论】:

    • 谢谢pskink。我看到了你的评论。我正在阅读文档。我正在尝试这个。
    • 一切都超级清晰。我将在我的代码中检查这一点并在此处发表评论。
    • btw CustomMultiChildLayout 支持开箱即用的动画,请参阅gist.github.com/pskink/ba475f88ba1853bec95ee9b7776e7184
    • 很抱歉回复晚了,这里是节日。您的答案在简单示例中效果很好。但是在我的代码中,我得到了这个RenderCustomMultiChildLayoutBox object was given an infinite size during layout. 错误,因为无限约束被设置为小部件树中的小部件,需要找到解决方法。我将此标记为答案,因为您的答案达到了查询中的要求。谢谢。
    • 很可能你在一些Row / Column 没有Expanded 小部件
    猜你喜欢
    • 1970-01-01
    • 2014-03-26
    • 1970-01-01
    • 1970-01-01
    • 2019-01-20
    • 2018-02-10
    • 2017-11-15
    • 2013-03-25
    • 1970-01-01
    相关资源
    最近更新 更多