Flutter'da CustomMultiChildLayout ve CustomSingleChildLayout nasıl kullanılır


10

Kullanım deneyimi olan bir kişi CustomSingleChildLayoutve CustomMultiChildLayoutsınıflar nasıl kullanılacağını detaylı olarak açıklayabilir (örnekler ile).

Flutter'da yeniyim ve bunları nasıl kullanacağımı anlamaya çalışıyorum. Ancak, belgeler korkunç ve net değil. İnternette örnekler bulmaya çalıştım, ancak başka belge yok.

Eğer yardım edebilirsen sonsuza dek minettar olurum.

Teşekkür ederim!


Bunları ne için kullanmak istediğinizi ekler misiniz?
João Soares

@ JoãoSoares Bu konuda endişelenmeyin çünkü kapsamlı bir cevap yazıyorum.
creativecreatorormaybenot

O zaman yüksek beklentiler!
João Soares

@ JoãoSoares Bitti, herhangi bir düzeltmeniz olup olmadığını bize bildirin.
creativecreatorormaybenot

@creativecreatorormaybenot Bu pek olası değildir. Cevaplarını daha önce gördüm. Her zamanki gibi harika bir cevap.
João Soares

Yanıtlar:


20

Her şeyden önce, mücadelelerinizi anlayabildiğim için size yardımcı olmaktan mutluluk duyduğumu söylemek istiyorum - bunu kendiniz de çözmenin faydaları var (belgeler inanılmaz).

CustomSingleChildLayoutSize açıkladıktan sonra ne olacağı belli CustomMultiChildLayoutolacak.

CustomMultiChildLayout

Bu widget'ın amacı, bu widget'a ilettiğiniz çocukları tek bir işlevde düzenlemenize izin verir , yani konumları ve boyutları birbirine bağlı olabilir, bu da önceden oluşturulmuş widget'ı kullanarak elde edemeyeceğiniz bir şeydir Stack.

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

Şimdi, çocuklarınızı düzenlemeye başlamadan önce atmanız gereken iki adım daha var :

  1. Geçtiğiniz her çocuğun bir çocuk childrenolması LayoutIdve aslında çocuk olarak göstermek istediğiniz widget'ı geçirmeniz gerekir LayoutId. Bu id, widget'larınızı benzersiz bir şekilde tanımlar ve bunları düzenlerken erişilebilir hale getirir:
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. MultiChildLayoutDelegateDüzen bölümünü işleyen bir alt sınıf oluşturmanız gerekir . Buradaki belgeler çok ayrıntılı görünüyor.
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;
}

Şimdi, tüm kurulum yapılır ve gerçek düzeni uygulamaya başlayabilirsiniz. Bunun için kullanabileceğiniz üç yöntem vardır:

  • hasChildHangi belirli olmadığını kontrol sağlayan id (hatırlamak LayoutId?) Geçildi childreno id çocuğu varsa, yani.

  • layoutChildher kimlik , her çocuk için tam olarak bir kez verilen ve size Sizeo çocuğu verecektir .

  • positionChild, konumu Offset(0, 0)belirttiğiniz herhangi bir ofsete değiştirmenize olanak tanır .

Kavramın şimdi oldukça açık olması gerektiğini hissediyorum, bu yüzden örnek için bir temsilci nasıl uygulanacağını göstereceğim 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.
        ),
      );
    }
  }
}

Diğer iki örnek belgeleri (çek hazırlama gelen biri de adım 2'de ) ve gerçek dünya Bir süre için cevap yazdım Örneğin feature_discovery: paketinde MultiChildLayoutDelegateuygulanmasını ve CustomMultiChildLayoutiçinde buildyöntemle .

Son adım, eski bir delege ile karşılaştırarak herhangi bir zamanda tekrar çağrılıp çağrılmayacağını kontrol eden shouldRelayoutyöntemiperformLayout geçersiz kılar (isteğe bağlı olarak da geçersiz kılabilirsiniz getSize) ve delegeyi kendinize ekleyebilirsiniz 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)
  ],
)

hususlar

  • Ben 1ve bu örnekte id s 2olarak kullandım , ancak bir kullanmak muhtemelen belirli kimlikleri varsa kimlikleri işlemek için en iyi yoldur.enum

  • Bir geçebilir Listenableiçin super(örneğin super(relayout: animation)) bunu genel olarak dinlenebilir dayalı düzen işlemini veya tetiği animasyon istiyorum.

CustomSingleChildLayout

Belgeler , yukarıda neyi iyi tanımladığımı açıklıyor ve burada, CustomSingleChildLayoutnasıl CustomMultiChildLayoutçalıştığını anladıktan sonra neden çok açık olacağını söylediğimi de göreceksiniz :

CustomMultiChildLayout , birden çok widget'ın boyutu ve konumlandırması arasında karmaşık ilişkiler olduğunda uygundur. Tek bir çocuğun düzenini kontrol etmek için CustomSingleChildLayout daha uygundur.

Bu aynı zamanda kullanımın CustomSingleChildLayoutyukarıda tarif ettiğim aynı ilkeleri izlediği, ancak herhangi bir kimliği olmadığı anlamına gelir, çünkü sadece tek bir çocuk vardır. Düzeni uygulamak için farklı yöntemlere sahip
bir SingleChildLayoutDelegatebunun yerine kullanmanız gerekir (hepsinin varsayılan davranışı vardır, bu nedenle teknik olarak hepsi geçersiz kılmak için isteğe bağlıdır ):

Diğer her şey tamamen aynıdır ( LayoutIdbunun yerine ihtiyacınız olmadığını ve sadece tek bir çocuğunuz olduğunu unutmayın children).


MultiChildRenderObjectWidget

Bu CustomMultiChildLayoutüzerine inşa edilmiş.
Bunu kullanmak Flutter hakkında daha derin bir bilgi gerektirir ve yine biraz daha karmaşıktır, ancak daha düşük bir seviye olduğu için daha fazla özelleştirme istiyorsanız daha iyi bir seçenektir. Bunun büyük bir avantajı CustomMultiChildLayoutvardır (genellikle daha fazla kontrol vardır):

CustomMultiChildLayout kendisini çocuklarına göre boyutlandıramaz ( akıl yürütme için daha iyi dokümantasyon konusuna bakın).

MultiChildRenderObjectWidgetBurada bariz nedenlerle nasıl kullanılacağını açıklamayacağım , ancak ilgileniyorsanız, 20 Ocak 2020'den sonra yaygın olarak kullandığım Flutter Clock mücadelesine gönderimi kontrol edebilirsiniz - bununla ilgili bir makaleMultiChildRenderObjectWidget de okuyabilirsiniz , ve bunların hepsinin nasıl çalıştığını biraz açıklamalı.

Şimdilik bunu mümkün MultiChildRenderObjectWidgetkılan şeyleri hatırlayabilirsiniz CustomMultiChildLayoutve doğrudan kullanmanız, kullanmamanız LayoutIdve bunun yerine RenderObjectana verilere doğrudan erişebilmeniz gibi bazı güzel faydalar sağlayacaktır .

Eğlenceli gerçek

Tüm kodu düz metinde (StackOverflow metin alanına) yazdım, bu yüzden hatalar varsa, lütfen bana işaret edin ve bunları düzeltirim.


1
Vay. Şaşırtıcı cevap. LayoutIdKüresel veya yerel olarak benzersiz olmalı mı ? küresel olarak, kardeş tipi widget'ların çocuklarında CustomMultiChildLayoutfarklı LayoutIdolmaları gerekir.
om-ha

1
@ om-ha Yerel olarak - kimlik, ana verilerinde saklanacak, LayoutIdyani bu verilere, kimliğe yalnızca doğrudan ebeveyn tarafından erişilecek :)
creativecreatorormaybenot

2
VAOV! Sen benim kurtarıcımsın! BU HAKKIMDA KONUŞUYORUM! çarpıntı belgelerinin böyle olması gerekir !! Bu sınıfların sadece normal belgelerle nasıl çalıştığını anlayabilmemin hiçbir yolu yoktu. ÇOK TEŞEKKÜR EDERİM!
Walter M

1
Gerçekten şaşırtıcı bir cevap. CustomMultiChildLayoutBir dahilinde grup otomatik yeniden boyutlandırma birden Metin widget için gereken senaryolarda bu kadar yararlıdır Columnait Rowbir örnek için, 's.
om-ha
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.