gpt4 book ai didi

flutter - 如何在 Flutter 中使用 CustomMultiChildLayout & CustomSingleChildLayout

转载 作者:行者123 更新时间:2023-12-04 17:42:45 53 4
gpt4 key购买 nike

有使用经验的人可以吗 CustomSingleChildLayout CustomMultiChildLayout 类能够详细解释(通过示例)如何使用它们。

我是 Flutter 的新手,正在尝试了解如何使用这些。但是,文档很糟糕,而且不清楚。我试图在互联网上搜索示例,但没有任何其他文档。

如果您能提供帮助,我将永远感激不尽。

谢谢!

最佳答案

首先,我想说我很高兴能帮助你解决这个问题,因为我能理解你的挣扎 - 自己解决它也有好处(文档很棒)。

什么 CustomSingleChildLayout在我解释之后,确实会很明显CustomMultiChildLayout给你。

CustomMultiChildLayout

这个小部件的重点是让您布局您在单个函数中传递给此小部件的子项,即它们的位置和大小可以相互依赖,这是您无法使用例如预建 Stack小部件。

CustomMultiChildLayout(
children: [
// Widgets you want to layout in a customized manner
],
)

现在,有 还有两步在开始给 child 安排之前,您需要采取以下措施:
  • 您传递给的每个 child children必须是 LayoutId 然后将您实际想要作为 child 显示的小部件传递给该 LayoutId . id将唯一标识您的小部件,使其在布局时可以访问:

  • CustomMultiChildLayout(
    children: [
    LayoutId(
    id: 1, // The id can be anything, i.e. any Object, also an enum value.
    child: Text('Widget one'), // This is the widget you actually want to show.
    ),
    LayoutId(
    id: 2, // You will need to refer to that id when laying out your children.
    child: Text('Widget two'),
    ),
    ],
    )
  • 您需要创建一个 MultiChildLayoutDelegate 处理布局部分的子类。这里的文档似乎非常详细。

  • class YourLayoutDelegate extends MultiChildLayoutDelegate {
    // You can pass any parameters to this class because you will instantiate your delegate
    // in the build function where you place your CustomMultiChildLayout.
    // I will use an Offset for this simple example.

    YourLayoutDelegate({this.position});

    final Offset position;
    }

    现在,所有设置都已完成,您可以开始实现实际布局。您可以使用三种方法:
  • hasChild ,它可以让您检查特定的 id (还记得 LayoutId 吗?)被传递给 children ,即如果该 ID 的 child 存在。
  • layoutChild ,您需要为每个 调用它id , 每个 child ,只提供一次,它会给你 Size那个 child 的。
  • positionChild ,它允许您从 Offset(0, 0) 更改位置到您指定的任何偏移量。

  • 我觉得现在这个概念应该很清楚了,这就是为什么我将说明如何为示例 CustomMultiChildLayout 实现委托(delegate)。 :

    class YourLayoutDelegate extends MultiChildLayoutDelegate {
    YourLayoutDelegate({this.position});

    final Offset position;

    @override
    void performLayout(Size size) {
    // `size` is the size of the `CustomMultiChildLayout` itself.

    Size leadingSize = Size.zero; // If there is no widget with id `1`, the size will remain at zero.
    // Remember that `1` here can be any **id** - you specify them using LayoutId.
    if (hasChild(1)) {
    leadingSize = layoutChild(
    1, // The id once again.
    BoxConstraints.loose(size), // This just says that the child cannot be bigger than the whole layout.
    );
    // No need to position this child if we want to have it at Offset(0, 0).
    }

    if (hasChild(2)) {
    final secondSize = layoutChild(
    2,
    BoxConstraints(
    // This is exactly the same as above, but this can be anything you specify.
    // BoxConstraints.loose is a shortcut to this.
    maxWidth: size.width,
    maxHeight: size.height,
    ),
    );

    positionChild(
    2,
    Offset(
    leadingSize.width, // This will place child 2 to the right of child 1.
    size.height / 2 - secondSize.height / 2, // Centers the second child vertically.
    ),
    );
    }
    }
    }

    另外两个例子是文档中的一个(检查准备步骤 2)和我为 feature_discovery 写的一个真实世界的例子。包裹: MultiChildLayoutDelegate implementation CustomMultiChildLayout in the build method .

    最后一步是覆盖 shouldRelayout method , 简单控制是否 performLayout应该通过与旧委托(delegate)进行比较,在任何给定时间点再次调用(可选地,您也可以覆盖 getSize )并将委托(delegate)添加到您的 CustomMultiChildLayout :

    class YourLayoutDelegate extends MultiChildLayoutDelegate {
    YourLayoutDelegate({this.position});

    final Offset position;

    @override
    void performLayout(Size size) {
    // ... (layout code from above)
    }

    @override
    bool shouldRelayout(YourLayoutDelegate oldDelegate) {
    return oldDelegate.position != position;
    }
    }

    CustomMultiChildLayout(
    delegate: YourLayoutDelegate(position: Offset.zero),
    children: [
    // ... (your children wrapped in LayoutId's)
    ],
    )

    注意事项
  • 我用过 12 id s 在本例中,但使用 enum如果您有特定的 ID,可能是处理 ID 的最佳方式。
  • 您可以通过 Listenablesuper (例如 super(relayout: animation) )如果您想为布局过程设置动画或基于一般的可听对象触发它。

  • CustomSingleChildLayout

    The documentation很好地解释了我上面描述的内容,在这里你也会明白我为什么这么说 CustomSingleChildLayout了解后会很明显 CustomMultiChildLayout作品:

    CustomMultiChildLayout is appropriate when there are complex relationships between the size and positioning of a multiple widgets. To control the layout of a single child, CustomSingleChildLayout is more appropriate.



    这也意味着使用 CustomSingleChildLayout遵循我上面描述的相同原则,但没有任何 id,因为只有一个 child 。
    您需要使用 SingleChildLayoutDelegate 相反,它有不同的实现布局的方法(它们都有默认行为,所以从技术上讲,它们都是 覆盖 的可选):
  • getConstraintsForChild ,相当于我传递给 layoutChild 的约束以上。
  • getPositionForChild ,相当于 positionChild以上。

  • 其他一切都完全相同(请记住,您不需要 LayoutId 并且只有一个 child 而不是 children )。

    MultiChildRenderObjectWidget

    这是什么 CustomMultiChildLayout建立在。
    使用它需要对 Flutter 有更深入的了解,也有点复杂,但如果你想要更多的自定义,它是更好的选择,因为它的级别更低。这有一个 少校 优于 CustomMultiChildLayout (一般来说,有更多的控制):
    CustomMultiChildLayout 不能大小 本身 基于其子项 (见 issue regarding better documentation for the reasoning)。

    怎么用 MultiChildRenderObjectWidget我就不解释了这里的原因显而易见,但如果您有兴趣,可以查看 my submission to the Flutter Clock challenge 2020 年 1 月 20 日之后,我使用 MultiChildRenderObjectWidget广泛 - 您还可以阅读 an article about this ,这应该解释一下它是如何工作的。

    现在你可以记住 MultiChildRenderObjectWidget是什么让 CustomMultiChildLayout可能,直接使用它会给你带来一些好处,比如不必使用 LayoutId而是能够访问 RenderObject的父数据直接。

    有趣的事实

    我用纯文本编写了所有代码(在 StackOverflow 文本字段中),所以如果有错误,请指出它们,我会修复它们。

    关于flutter - 如何在 Flutter 中使用 CustomMultiChildLayout & CustomSingleChildLayout,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59483051/

    53 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com