Flutter में CustomMultiChildLayout और CustomSingleChildLayout का उपयोग कैसे करें


10

क्या उपयोग करने CustomSingleChildLayoutऔर CustomMultiChildLayoutकक्षाओं में अनुभव रखने वाला कोई व्यक्ति उन्हें उपयोग करने के तरीके (उदाहरण के साथ) में विस्तार से बता सकता है।

मैं स्पंदन के लिए नया हूं और यह समझने की कोशिश कर रहा हूं कि इनका उपयोग कैसे किया जाए। हालांकि, प्रलेखन भयानक है और स्पष्ट नहीं है। मैंने उदाहरण के लिए इंटरनेट को कुरेदने की कोशिश की, लेकिन कोई अन्य दस्तावेज नहीं है।

यदि आप मदद कर सकते हैं तो मैं सदा आभारी रहूंगा।

धन्यवाद!


क्या आप कृपया इसमें जोड़ सकते हैं कि आप उनके लिए क्या उपयोग करना चाहते हैं?
जोआ सोरेस

@ JoãoSoares इस बारे में चिंता न करें क्योंकि मैं एक व्यापक उत्तर लिख रहा हूं।
क्रिएटिवक्रोम्योरमायबेनॉट

उच्च उम्मीदें तब!
जोआ सोरेस

@ जोआओसारेस हो गया, मुझे बताएं कि क्या आपके पास कोई सुधार है।
क्रिएटिवक्रैटमोरमैबिनोट

@creativecreatorormaybenot यह बहुत संभावना नहीं होगी। मैंने पहले आपके जवाब देखे हैं। महान जवाब, हमेशा की तरह।
जोआ सोरेस

जवाबों:


20

सबसे पहले, मैं यह कहना चाहता हूं कि मुझे आपकी मदद करने में खुशी है क्योंकि मैं आपके संघर्षों को समझ सकता हूं - इसके बारे में खुद से भी पता लगाने के फायदे हैं (प्रलेखन अद्भुत है)।

आपके CustomSingleChildLayoutसमझाने के बाद क्या स्पष्ट होगा CustomMultiChildLayout

CustomMultiChildLayout

इस विजेट की बात यह है कि आप उन बच्चों को लेआउट करने की अनुमति देते हैं जिन्हें आप एक ही फ़ंक्शन में इस विजेट में पास करते हैं, अर्थात उनकी स्थिति और आकार एक-दूसरे पर निर्भर कर सकते हैं, जो कि आपके द्वारा पूर्वनिर्मित विजेट का उपयोग करके प्राप्त नहीं किया जा सकता हैStack

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

अब, दो और कदम उठाने की जरूरत है, इससे पहले कि आप अपने बच्चों को रखना शुरू कर सकें:

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

अब, सभी सेटअप किया जाता है और आप वास्तविक लेआउट को लागू करना शुरू कर सकते हैं। इसके लिए आप तीन तरीके अपना सकते हैं:

  • hasChild, जो आपको यह जांचने देता है कि क्या कोई विशेष आईडी (याद LayoutId?) पास की गई थी children, अर्थात यदि उस आईडी का कोई बच्चा मौजूद है।

  • layoutChild, जिसे आपको प्रत्येक आईडी , प्रत्येक बच्चे के लिए कॉल करने की आवश्यकता है , बिल्कुल एक बार प्रदान किया गया है और यह आपको 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 ) और एक वास्तविक दुनिया उदाहरण के लिए मैं कुछ समय पहले लिखा था feature_discovery: पैकेज MultiChildLayoutDelegateकार्यान्वयन और CustomMultiChildLayoutमें buildविधि

अंतिम चरण उस 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)
  ],
)

विचार

  • मैं प्रयोग किया जाता है 1और 2के रूप में आईडी इस उदाहरण में है, लेकिन का उपयोग कर एक enumशायद सबसे अच्छा तरीका है अगर आप विशिष्ट आईडी है आईडी को संभालने के लिए है।

  • आप एक पारित कर सकते हैं Listenableकरने के लिए super(उदाहरण के लिए super(relayout: animation)) यदि आप लेआउट प्रक्रिया या ट्रिगर यह सामान्य रूप में एक listenable के आधार पर चेतन करना चाहते हैं।

CustomSingleChildLayout

प्रलेखन बताता है कि मैंने वास्तव में अच्छी तरह से ऊपर वर्णित किया है और यहां आप यह भी देखेंगे कि मैंने क्यों कहा कि CustomSingleChildLayoutयह समझने के बाद बहुत स्पष्ट होगा कि कैसे CustomMultiChildLayoutकाम करता है:

CustomMultiChildLayout उपयुक्त है जब कई विजेट के आकार और स्थिति के बीच जटिल संबंध होते हैं। एकल बच्चे के लेआउट को नियंत्रित करने के लिए, CustomSingleChildLayout अधिक उपयुक्त है।

इसका मतलब यह भी है कि CustomSingleChildLayoutउन्हीं सिद्धांतों का उपयोग करना, जो मैंने ऊपर वर्णित किए हैं, लेकिन बिना किसी आईडी के क्योंकि केवल एक ही बच्चा है।
आपको SingleChildLayoutDelegateइसके बजाय उपयोग करने की आवश्यकता है , जिसमें लेआउट को लागू करने के लिए अलग-अलग तरीके हैं (वे सभी डिफ़ॉल्ट व्यवहार हैं, इसलिए वे तकनीकी रूप से ओवरराइड करने के लिए सभी वैकल्पिक हैं ):

  • getConstraintsForChild, जो मैं layoutChildऊपर पारित बाधाओं के बराबर है ।

  • getPositionForChild, जो positionChildऊपर के बराबर है ।

बाकी सब कुछ बिल्कुल वैसा ही है (याद रखें कि आपको ज़रूरत नहीं है LayoutIdऔर केवल एक ही बच्चा है children)।


MultiChildRenderObjectWidget

इस CustomMultiChildLayoutपर बनाया गया है।
इसका उपयोग करने के लिए फ़्लटर के बारे में और भी गहन ज्ञान की आवश्यकता होती है और फिर से थोड़ा और अधिक जटिल होता है, लेकिन यह बेहतर विकल्प है यदि आप अधिक अनुकूलन चाहते हैं क्योंकि यह और भी निम्न स्तर है। इसका एक प्रमुख लाभ है CustomMultiChildLayout(आम तौर पर, अधिक नियंत्रण होता है):

CustomMultiChildLayout अपने बच्चों के आधार पर खुद को आकार नहीं दे सकते हैं ( तर्क के लिए बेहतर प्रलेखन के बारे में समस्या देखें)।

मैं MultiChildRenderObjectWidgetस्पष्ट कारणों के लिए यहां उपयोग करने का तरीका नहीं बताऊंगा , लेकिन यदि आप रुचि रखते हैं, तो आप 20 जनवरी, 2020 के बाद फ़्लटर क्लॉक चुनौती को प्रस्तुत कर सकते हैं , जिसमें मैं MultiChildRenderObjectWidgetबड़े पैमाने पर उपयोग करता हूं - आप इस बारे में एक लेख भी पढ़ सकते हैं , जो यह सब कैसे काम करता है की एक सा समझा देना चाहिए।

अभी के लिए आप यह याद रख सकते हैं कि MultiChildRenderObjectWidgetजो CustomMultiChildLayoutसंभव है वह करता है और इसका सीधे उपयोग करने से आपको कुछ अच्छे लाभ मिलेंगे जैसे कि उपयोग न करना LayoutIdऔर इसके बजाय RenderObjectसीधे माता-पिता के डेटा तक पहुंच बनाने में सक्षम होना ।

मजेदार तथ्य

मैंने सभी कोड सादे पाठ (StackOverflow पाठ क्षेत्र में) में लिखे थे, इसलिए यदि कोई त्रुटियां हैं, तो कृपया उन्हें मुझे इंगित करें और मैं उन्हें ठीक कर दूंगा।


1
वाह। अद्भुत जवाब। LayoutIdविश्व स्तर पर या स्थानीय स्तर पर अद्वितीय होना चाहिए ? विश्व स्तर पर अर्थात अपने बच्चों में CustomMultiChildLayoutअलग-अलग प्रकार के विगेट्स रखने की आवश्यकता होती है LayoutId
ओम-हा

1
@ om-ha स्थानीय रूप से - आईडी को माता-पिता के डेटा में संग्रहीत किया जाएगा LayoutId, जिसका अर्थ है कि यह डेटा, आईडी, केवल प्रत्यक्ष माता-पिता द्वारा एक्सेस किया जाएगा :)
Creativecreatorormaybenot

2
वाह! तुम मेरे तारणहार हो! मेरे द्वारा इसी के बारे में बात की जा रही है! इस तरह से फड़फड़ाहट प्रलेखन होना चाहिए !! कोई तरीका नहीं था कि मैं यह पता लगा पाऊं कि इन वर्गों ने सिर्फ सामान्य प्रलेखन के साथ कैसे काम किया। आपको बहुत - बहुत धन्यवाद!
वाल्टर एम

1
अद्भुत जवाब वास्तव में। CustomMultiChildLayoutपरिदृश्यों जहाँ आप एक के भीतर समूह ऑटो आकार एकाधिक पाठ विजेट की जरूरत में इतना उपयोगी है Columnकी Row, के एक उदाहरण के लिए।
ओम-हा
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.