FlutterでCustomMultiChildLayoutとCustomSingleChildLayoutを使用する方法


10

使用した経験を持つ缶誰かCustomSingleChildLayoutCustomMultiChildLayoutクラスは、それらを使用する方法で(例で)詳細に説明することができます。

私はFlutterを初めて使用し、これらの使用方法を理解しようとしています。ただし、ドキュメントは恐ろしく、明確ではありません。例としてインターネットを調べてみましたが、他のドキュメントはありません。

あなたが助けてくれるなら、私は永遠に感謝します。

ありがとうございました!


それらを何に使用したいかを追加していただけませんか?
ジョアン・ソアレス

@JoãoSoares私は広範な回答を書いているので、心配しないでください。
creativecreatoror19'19年

そのときは大きな期待!
ジョアン・ソアレス

@JoãoSoares完了しました。修正がある場合はお知らせください。
creativecreatoror'not

@creativecreatorormaybenotそれは非常にありそうもないでしょう。以前にあなたの答えを見たことがあります。いつものように素晴らしい答えです。
ジョアン・ソアレス

回答:


20

まず第一に、私はあなたの苦労を理解できるので、これを手伝って喜んでいると言いたいです-自分でそれを理解することにも利点があります(ドキュメントは素晴らしいです)。

CustomSingleChildLayoutCustomMultiChildLayoutあなたに説明した後、何が明白になるでしょう。

CustomMultiChildLayout

このウィジェットのポイントは、このウィジェットに渡す子を単一の関数でレイアウトできることです。つまり、それらの位置とサイズは互いに依存する可能性があります。これは、たとえば事前に作成されたものを使用して達成できないものですStackます。ウィジェット。

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

さて、さらに2つのステップがあります子供を配置する前に、次のをする必要があります。

  1. 渡すすべての子はであるchildren必要があり、LayoutId実際に子として表示したいウィジェットをそのウィジェットに渡しますLayoutIdid独自にそれらをレイアウトするときにそれらにアクセスすること、あなたのウィジェットを識別します。
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'),
    ),
  ],
)
  1. 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;
}

これですべての設定が完了し、実際のレイアウトの実装を開始できます。そのために使用できる方法は3つあります。

  • hasChildこれにより、特定のID(覚えているLayoutId?)がに渡されたかどうかchildren、つまりそのIDの子が存在するかどうかを確認できます。

  • layoutChild、すべてのid、すべての子を呼び出す必要があり、正確に一度だけ提供されSize、その子のを提供します。

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

他の2つの例は、ドキュメントからの例(チェックの準備ステップ2)と、パッケージについて少し前に書いた実際の例ですfeature_discoveryMultiChildLayoutDelegate実装CustomMultiChildLayoutbuild方法を

最後のステップは、shouldRelayoutメソッドをオーバーライドすることです。このメソッドperformLayout、古いデリゲートと比較して(任意でをオーバーライドすることもできます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;
  }
}
CustomMultiChildLayout(
  delegate: YourLayoutDelegate(position: Offset.zero),
  children: [
    // ... (your children wrapped in LayoutId's)
  ],
)

考慮事項

  • この例では、12IDとして使用しましたenumが、特定のIDがある場合、IDを処理するには、おそらくを使用するのがおそらく最良の方法です。

  • あなたは渡すことができますListenablesuper(例えばsuper(relayout: animation)、あなたが、それは一般的に聴きに基づいてレイアウト処理やトリガーをアニメーション化する場合)。

CustomSingleChildLayout

ドキュメンテーションは私が上で説明したことを本当によく説明しており、ここでは、私がそれCustomSingleChildLayoutがどのようにCustomMultiChildLayout機能するかを理解した後に非常に明白になると私が言った理由も見るでしょう:

CustomMultiChildLayoutは、複数のウィジェットのサイズと配置の間に複雑な関係がある場合に適しています。単一の子のレイアウトを制御するには、CustomSingleChildLayoutがより適切です。

これは、使用CustomSingleChildLayoutが上記で説明したのと同じ原則に従うことを意味しますが、子が1つしかないため、IDはありません。代わりに、レイアウトを実装するためのさまざまなメソッドを持つ
を使用する必要がありSingleChildLayoutDelegateます(すべてデフォルトの動作があるため、技術的にはすべてオーバーライドできます)。

他はすべてまったく同じです(必要LayoutIdではなく、の代わりに子が1つしかないことに注意してくださいchildren)。


MultiChildRenderObjectWidget

これがCustomMultiChildLayout上に構築されたものです。
これを使用するには、Flutterに関するさらに深い知識が必要であり、やはり少し複雑ですが、レベルがさらに低いため、より多くのカスタマイズが必要な場合は、より良いオプションです。これには、に1つの利点がありますCustomMultiChildLayout(一般に、より多くの制御が可能です)。

CustomMultiChildLayout サイズができない自分自身をその子に基づいて(参照推論のためのより良いマニュアルに関する問題)。

MultiChildRenderObjectWidgetここでは明確な理由で使用方法を説明しませんが、興味がある場合は、2020年1月20日以降に私が広く使用しているFlutter Clockチャレンジへの私の提出をチェックMultiChildRenderObjectWidgetできます。この記事を、それはすべてがどのように機能するかを少し説明するはずです。

今のMultiChildRenderObjectWidgetところ、CustomMultiChildLayoutそれが可能であり、それを直接使用するLayoutIdと、使用する必要がなく、代わりにRenderObjectの親データに直接アクセスできるなど、いくつかの素晴らしい利点が得られることを覚えておくことができます。

楽しい事実

私はすべてのコードをプレーンテキスト(StackOverflowテキストフィールド)で記述したので、エラーが発生した場合は指摘してください。修正します。


1
ワオ。すばらしい答え。はLayoutIdグローバルまたはローカルで一意である必要がありますか?つまり、タイプの兄弟ウィジェットでは、子にCustomMultiChildLayout別個LayoutIdのが必要です。
om-ha

1
@ om-haローカル-idはの親データに保存されますLayoutId。つまり、このデータ、idは直接の親によってのみアクセスされます:)
creativecreatorormaybenot

2
うわー!あなたは私の救世主です!これが私が話していることです!これはフラッターのドキュメントがどうあるべきかです!! これらのクラスが通常のドキュメントだけでどのように機能するかを理解することはできませんでした。どうもありがとうございます!
Walter M

1
本当に素晴らしい答えです。たとえば、CustomMultiChildLayout複数のTextウィジェットをa Columnの内で自動サイズ変更する必要があるシナリオでは非常に便利ですRow
om-ha
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.