如何在Flutter中使用CustomMultiChildLayout和CustomSingleChildLayout

问题描述 投票:5回答:1

具有使用CustomSingleChildLayoutCustomSingleChildLayout类的经验的人可以(使用示例)详细解释如何使用它们。

我是Flutter的新手,正在尝试了解如何使用它们。但是,该文档太糟糕了,不清楚。我尝试在Internet上搜索示例,但没有其他文档。

如果您能提供帮助,我将万分感谢。

谢谢!

flutter dart flutter-layout
1个回答
8
投票

首先,我很高兴能为您提供帮助,因为我可以理解您的挣扎-自己解决问题也有好处(文档很棒)。

CustomMultiChildLayout的作用在我向您解释CustomMultiChildLayout之后将显而易见。

CustomSingleChildLayout

此小部件的要点是允许您通过单个函数layout传递给此小部件的子代,即,它们的位置和大小可以相互依赖,这是您无法实现的使用例如预建的CustomMultiChildLayout小部件。

CustomMultiChildLayout

现在,您需要执行另外两个步骤,然后才能开始布置孩子:

  1. 传递给CustomMultiChildLayout的每个孩子都必须是Stack,然后将实际上要显示为孩子的小部件传递给CustomMultiChildLayout( children: [ // Widgets you want to layout in a customized manner ], ) children将唯一地标识您的小部件,从而在布局它们时可以访问它们:
LayoutId
  1. 您需要创建一个处理布局部分的LayoutId子类。这里的文档似乎非常复杂。
LayoutId

现在,所有设置都已完成,您可以开始实施实际布局。您可以使用三种方法:

  • id,可让您检查是否将特定的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,即是否存在该ID的孩子。

  • [MultiChildLayoutDelegate,您需要为每个id,每个孩子提供一个[[恰好一次]]调用,它将为您提供该孩子的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,可让您将位置从hasChild更改为您指定的任何偏移量。
  • 我觉得现在概念应该很清楚了,这就是为什么我将说明如何为示例LayoutId实现委托的原因:>

    children

另外两个示例是文档中的一个示例(检查准备

步骤2

)和一个我为layoutChild包写了一段时间的real world
示例:layoutChildSize最后一步是覆盖positionChild,它通过与旧的委托进行比较,简单地控制是否应在任何给定时间点再次调用positionChild,(可选地,您也可以覆盖Offset(0, 0))并添加委托到您的CustomMultiChildLayout

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. ), ); } } }

feature_discovery
注意事项

,但是如果您有特定的ID,则使用MultiChildLayoutDelegate可能是处理ID的最佳方法。
  • 如果您要为布局过程设置动画或基于一般的可听性来触发它,则可以将CustomMultiChildLayout in the build method传递给CustomMultiChildLayout(例如build)。
  • shouldRelayout method

    [shouldRelayout很好地解释了我在上面描述的内容,在这里您还将看到为什么我说performLayout在理解getSize的工作原理之后变得非常明显:

    当多个小部件的大小和位置之间存在复杂的关系时,

    getSize是适当的。要控制单个孩子的布局,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; } } 遵循我上面描述的相同原理,但是没有ID,因为只有一个孩子。您需要使用CustomMultiChildLayout( delegate: YourLayoutDelegate(position: Offset.zero), children: [ // ... (your children wrapped in LayoutId's) ], ) 代替,它具有用于实现布局的不同方法(它们均具有默认行为,因此从技术上讲,它们对于

    override

    都是可选的):
    • 1,等效于我传递给以上2的约束。

  • enum,相当于上面的Listenable
  • 其他所有内容都完全相同(请记住,您不需要super,只有一个孩子而不是super(relayout: animation))。


    CustomSingleChildLayout

    这是CustomSingleChildLayout的基础。使用此功能需要更深入的Flutter知识,并且再次复杂一些,但是如果您需要更多的自定义设置,则它是更好的选择,因为它甚至更低。与The documentation相比,这有一个

    major

    优势(通常有更多控制权):

    CustomSingleChildLayout 无法调整大小

    本身基于其子级(请参阅CustomMultiChildLayout)。
    出于明显的原因,我不会在这里解释如何使用CustomMultiChildLayout,但是如果您有兴趣,您可以在2020年1月20日之后签出CustomSingleChildLayout,在此我会大量使用CustomSingleChildLayout-我还将写一封关于此的文章,应该解释一下所有这些如何工作。

    [现在您可以记住SingleChildLayoutDelegate是使SingleChildLayoutDelegate成为可能的原因,直接使用它会为您带来一些好处,例如不必使用getConstraintsForChild而可以访问getConstraintsForChild的父数据直接。

    有趣的事实

    我用纯文本(在StackOverflow文本字段中)编写了所有代码,因此,如果有错误,请向我指出,然后我将对其进行修复。

    © www.soinside.com 2019 - 2024. All rights reserved.