सबसे पहले, मैं यह कहना चाहता हूं कि मुझे आपकी मदद करने में खुशी है क्योंकि मैं आपके संघर्षों को समझ सकता हूं - इसके बारे में खुद से भी पता लगाने के फायदे हैं (प्रलेखन अद्भुत है)।
आपके CustomSingleChildLayout
समझाने के बाद क्या स्पष्ट होगा CustomMultiChildLayout
।
इस विजेट की बात यह है कि आप उन बच्चों को लेआउट करने की अनुमति देते हैं जिन्हें आप एक ही फ़ंक्शन में इस विजेट में पास करते हैं, अर्थात उनकी स्थिति और आकार एक-दूसरे पर निर्भर कर सकते हैं, जो कि आपके द्वारा पूर्वनिर्मित विजेट का उपयोग करके प्राप्त नहीं किया जा सकता हैStack
।
CustomMultiChildLayout(
children: [
// Widgets you want to layout in a customized manner
],
)
अब, दो और कदम उठाने की जरूरत है, इससे पहले कि आप अपने बच्चों को रखना शुरू कर सकें:
- हर बच्चा जिसे आप पास होना चाहते
children
हैं, वह है LayoutId
और आप उस विजेट को पास करते हैं जिसे आप वास्तव में उस बच्चे के रूप में दिखाना चाहते हैं 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
, जो आपको यह जांचने देता है कि क्या कोई विशेष आईडी (याद 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
यह समझने के बाद बहुत स्पष्ट होगा कि कैसे CustomMultiChildLayout
काम करता है:
CustomMultiChildLayout उपयुक्त है जब कई विजेट के आकार और स्थिति के बीच जटिल संबंध होते हैं। एकल बच्चे के लेआउट को नियंत्रित करने के लिए, CustomSingleChildLayout अधिक उपयुक्त है।
इसका मतलब यह भी है कि CustomSingleChildLayout
उन्हीं सिद्धांतों का उपयोग करना, जो मैंने ऊपर वर्णित किए हैं, लेकिन बिना किसी आईडी के क्योंकि केवल एक ही बच्चा है।
आपको SingleChildLayoutDelegate
इसके बजाय उपयोग करने की आवश्यकता है , जिसमें लेआउट को लागू करने के लिए अलग-अलग तरीके हैं (वे सभी डिफ़ॉल्ट व्यवहार हैं, इसलिए वे तकनीकी रूप से ओवरराइड करने के लिए सभी वैकल्पिक हैं ):
बाकी सब कुछ बिल्कुल वैसा ही है (याद रखें कि आपको ज़रूरत नहीं है LayoutId
और केवल एक ही बच्चा है children
)।
इस CustomMultiChildLayout
पर बनाया गया है।
इसका उपयोग करने के लिए फ़्लटर के बारे में और भी गहन ज्ञान की आवश्यकता होती है और फिर से थोड़ा और अधिक जटिल होता है, लेकिन यह बेहतर विकल्प है यदि आप अधिक अनुकूलन चाहते हैं क्योंकि यह और भी निम्न स्तर है। इसका एक प्रमुख लाभ है CustomMultiChildLayout
(आम तौर पर, अधिक नियंत्रण होता है):
CustomMultiChildLayout
अपने बच्चों के आधार पर खुद को आकार नहीं दे सकते हैं ( तर्क के लिए बेहतर प्रलेखन के बारे में समस्या देखें)।
मैं MultiChildRenderObjectWidget
स्पष्ट कारणों के लिए यहां उपयोग करने का तरीका नहीं बताऊंगा , लेकिन यदि आप रुचि रखते हैं, तो आप 20 जनवरी, 2020 के बाद फ़्लटर क्लॉक चुनौती को प्रस्तुत कर सकते हैं , जिसमें मैं MultiChildRenderObjectWidget
बड़े पैमाने पर उपयोग करता हूं - आप इस बारे में एक लेख भी पढ़ सकते हैं , जो यह सब कैसे काम करता है की एक सा समझा देना चाहिए।
अभी के लिए आप यह याद रख सकते हैं कि MultiChildRenderObjectWidget
जो CustomMultiChildLayout
संभव है वह करता है और इसका सीधे उपयोग करने से आपको कुछ अच्छे लाभ मिलेंगे जैसे कि उपयोग न करना LayoutId
और इसके बजाय RenderObject
सीधे माता-पिता के डेटा तक पहुंच बनाने में सक्षम होना ।
मजेदार तथ्य
मैंने सभी कोड सादे पाठ (StackOverflow पाठ क्षेत्र में) में लिखे थे, इसलिए यदि कोई त्रुटियां हैं, तो कृपया उन्हें मुझे इंगित करें और मैं उन्हें ठीक कर दूंगा।