Compose में फ़्लो लेआउट

FlowRow और FlowColumn, Row और Column जैसे कंपोज़ेबल हैं. हालांकि, इनमें यह अंतर है कि कंटेनर में जगह खत्म होने पर, आइटम अगली लाइन में चले जाते हैं. इससे कई लाइनें या कॉलम बनते हैं. maxItemsInEachRow या maxItemsInEachColumn को सेट करके, एक लाइन में मौजूद आइटम की संख्या को भी कंट्रोल किया जा सकता है. रिस्पॉन्सिव लेआउट बनाने के लिए, अक्सर FlowRow और FlowColumn का इस्तेमाल किया जा सकता है. अगर आइटम किसी डाइमेंशन के लिए बहुत बड़े हैं, तो कॉन्टेंट नहीं कटेगा. साथ ही, maxItemsInEach* और Modifier.weight(weight) के कॉम्बिनेशन का इस्तेमाल करके, ऐसे लेआउट बनाए जा सकते हैं जो ज़रूरत पड़ने पर किसी लाइन या कॉलम की चौड़ाई को भरते/बढ़ाते हैं.

इसका सामान्य उदाहरण, चिप या फ़िल्टर करने वाले यूज़र इंटरफ़ेस (यूआई) के लिए है:

FlowRow में पांच चिप, जो जगह न होने पर अगली लाइन में ओवरफ़्लो दिखाती हैं.
पहली इमेज. FlowRow का उदाहरण

बुनियादी इस्तेमाल

FlowRow या FlowColumn का इस्तेमाल करने के लिए, ये कंपोज़ेबल बनाएं और उनमें ऐसे आइटम रखें जो स्टैंडर्ड फ़्लो के मुताबिक हों:

@Composable
private fun FlowRowSimpleUsageExample() {
    FlowRow(modifier = Modifier.padding(8.dp)) {
        ChipItem("Price: High to Low")
        ChipItem("Avg rating: 4+")
        ChipItem("Free breakfast")
        ChipItem("Free cancellation")
        ChipItem("£50 pn")
    }
}

इस स्निपेट की वजह से, ऊपर दिखाया गया यूज़र इंटरफ़ेस (यूआई) दिखता है. इसमें पहली लाइन में जगह न होने पर, आइटम अपने-आप अगली लाइन में चले जाते हैं.

फ़्लो लेआउट की सुविधाएं

फ़्लो लेआउट में ये सुविधाएं और प्रॉपर्टी होती हैं. इनका इस्तेमाल करके, अपने ऐप्लिकेशन में अलग-अलग लेआउट बनाए जा सकते हैं.

मुख्य ऐक्सिस का अरेंजमेंट: हॉरिज़ॉन्टल या वर्टिकल अरेंजमेंट

मुख्य ऐक्सिस वह ऐक्सिस होता है जिस पर आइटम रखे जाते हैं. उदाहरण के लिए, FlowRow में आइटम हॉरिज़ॉन्टल तरीके से रखे जाते हैं. FlowRow में मौजूद horizontalArrangement पैरामीटर, आइटम के बीच खाली जगह को बांटने के तरीके को कंट्रोल करता है.

यहां दी गई टेबल में, FlowRow के लिए आइटम पर horizontalArrangement सेट करने के उदाहरण दिए गए हैं:

हॉरिज़ॉन्टल अरेंजमेंट को FlowRow पर सेट किया गया

नतीजा

Arrangement.Start (Default)

आइटम, शुरुआत के हिसाब से क्रम में लगाए गए हैं

Arrangement.SpaceBetween

आइटम के बीच स्पेस देकर उन्हें व्यवस्थित करना

Arrangement.Center

आइटम बीच में रखे गए हैं

Arrangement.End

आइटम को आखिर में व्यवस्थित किया गया

Arrangement.SpaceAround

आइटम के बीच में स्पेस देकर व्यवस्थित किया गया है

Arrangement.spacedBy(8.dp)

आइटम के बीच तय डीपी का स्पेस

FlowColumn के लिए, verticalArrangement के साथ मिलते-जुलते विकल्प उपलब्ध हैं. इनमें Arrangement.Top डिफ़ॉल्ट विकल्प है.

क्रॉस ऐक्सिस अरेंजमेंट

क्रॉस ऐक्सिस, मुख्य ऐक्सिस की उलटी दिशा में मौजूद ऐक्सिस होता है. उदाहरण के लिए, FlowRow में यह वर्टिकल ऐक्सिस है. कंटेनर में मौजूद कॉन्टेंट को क्रॉस ऐक्सिस में व्यवस्थित करने का तरीका बदलने के लिए, FlowRow के लिए verticalArrangement और FlowColumn के लिए horizontalArrangement का इस्तेमाल करें.

FlowRow के लिए, इस टेबल में आइटम पर अलग-अलग verticalArrangement सेट करने के उदाहरण दिए गए हैं:

FlowRow पर वर्टिकल अरेंजमेंट सेट किया गया

नतीजा

Arrangement.Top (Default)

कंटेनर के ऊपर की व्यवस्था

Arrangement.Bottom

कंटेनर के सबसे नीचे मौजूद एलिमेंट का अरेंजमेंट

Arrangement.Center

कंटेनर को बीच में अलाइन करना

FlowColumn के लिए, horizontalArrangement के साथ मिलते-जुलते विकल्प उपलब्ध हैं. डिफ़ॉल्ट क्रॉस ऐक्सिस अरेंजमेंट Arrangement.Start है.

अलग-अलग आइटम अलाइन करना

ऐसा हो सकता है कि आपको पंक्ति में मौजूद अलग-अलग आइटम को अलग-अलग अलाइनमेंट के साथ रखना हो. यह verticalArrangement और horizontalArrangement से अलग है, क्योंकि यह आइटम को मौजूदा लाइन में अलाइन करता है. Modifier.align() की मदद से, इसे लागू किया जा सकता है.

उदाहरण के लिए, जब किसी FlowRow में मौजूद आइटम की ऊंचाई अलग-अलग होती है, तो पंक्ति सबसे बड़े आइटम की ऊंचाई के हिसाब से अडजस्ट हो जाती है. साथ ही, आइटम पर Modifier.align(alignmentOption) लागू हो जाता है:

FlowRow पर वर्टिकल अलाइनमेंट सेट किया गया

नतीजा

Alignment.Top (Default)

आइटम ऊपर की ओर अलाइन किए गए

Alignment.Bottom

आइटम नीचे की ओर अलाइन किए गए हैं

Alignment.CenterVertically

आइटम बीच में अलाइन किए गए हैं

FlowColumn के लिए, मिलते-जुलते विकल्प उपलब्ध हैं. डिफ़ॉल्ट अलाइनमेंट Alignment.Start है.

लाइन या कॉलम में आइटम की ज़्यादा से ज़्यादा संख्या

maxItemsInEachRow या maxItemsInEachColumn पैरामीटर, मुख्य ऐक्सिस में मौजूद आइटम की ज़्यादा से ज़्यादा संख्या तय करते हैं. इससे यह तय होता है कि अगली लाइन में रैप करने से पहले, एक लाइन में कितने आइटम दिखाए जा सकते हैं. डिफ़ॉल्ट वैल्यू Int.MAX_INT है. इससे ज़्यादा से ज़्यादा आइटम जोड़े जा सकते हैं. हालांकि, इसके लिए ज़रूरी है कि आइटम का साइज़, लाइन में फ़िट होने लायक हो.

उदाहरण के लिए, maxItemsInEachRow सेट करने पर, शुरुआती लेआउट में सिर्फ़ तीन आइटम दिखेंगे:

कोई अधिकतम सीमा सेट नहीं है

maxItemsInEachRow = 3

फ़्लो की लाइन पर कोई मैक्सिमम वैल्यू सेट नहीं है फ़्लो रो में सेट किए गए आइटम की संख्या ज़्यादा से ज़्यादा है

आइटम का वज़न

Weight, किसी आइटम को उसके फ़ैक्टर और उस लाइन पर मौजूद जगह के आधार पर बड़ा करता है जिसमें उसे रखा गया है. सबसे ज़रूरी बात यह है कि FlowRow और Row में अंतर होता है. यह अंतर इस बात से तय होता है कि किसी आइटम की चौड़ाई का हिसाब लगाने के लिए, वेट का इस्तेमाल कैसे किया जाता है. Rows के लिए, वज़न Row में मौजूद सभी आइटम के आधार पर तय होता है. FlowRow के साथ, वज़न उस लाइन में मौजूद आइटम के आधार पर तय होता है जिसमें कोई आइटम रखा गया है, न कि FlowRow कंटेनर में मौजूद सभी आइटम के आधार पर.

उदाहरण के लिए, अगर आपके पास चार आइटम हैं और वे सभी एक लाइन में हैं, तो हर आइटम का वज़न 1f, 2f, 1f और 3f अलग-अलग होगा. कुल वज़न 7f होगा. किसी पंक्ति या कॉलम में बची हुई जगह को 7f से बांटा जाएगा. इसके बाद, हर आइटम की चौड़ाई का हिसाब इस फ़ॉर्मूले से लगाया जाएगा: weight * (remainingSpace / totalWeight).

ग्रिड जैसा लेआउट बनाने के लिए, Modifier.weight और आइटम की ज़्यादा से ज़्यादा संख्या के साथ FlowRow या FlowColumn का इस्तेमाल किया जा सकता है. यह तरीका, रिस्पॉन्सिव लेआउट बनाने के लिए मददगार है. ये लेआउट, आपके डिवाइस के साइज़ के हिसाब से अडजस्ट हो जाते हैं.

वेट का इस्तेमाल करके, कई तरह के काम किए जा सकते हैं. यहां इसके कुछ उदाहरण दिए गए हैं. इसका एक उदाहरण ग्रिड है, जिसमें आइटम एक ही साइज़ के होते हैं. जैसा कि यहां दिखाया गया है:

फ़्लो लाइन की मदद से ग्रिड बनाया गया
दूसरी इमेज. ग्रिड बनाने के लिए FlowRow का इस्तेमाल करना

एक जैसे साइज़ के आइटम की ग्रिड बनाने के लिए, यह तरीका अपनाएं:

val rows = 3
val columns = 3
FlowRow(
    modifier = Modifier.padding(4.dp),
    horizontalArrangement = Arrangement.spacedBy(4.dp),
    maxItemsInEachRow = rows
) {
    val itemModifier = Modifier
        .padding(4.dp)
        .height(80.dp)
        .weight(1f)
        .clip(RoundedCornerShape(8.dp))
        .background(MaterialColors.Blue200)
    repeat(rows * columns) {
        Spacer(modifier = itemModifier)
    }
}

अहम बात यह है कि अगर कोई दूसरा आइटम जोड़ा जाता है और उसे नौ के बजाय 10 बार दोहराया जाता है, तो आखिरी आइटम पूरी आखिरी कॉलम को घेर लेता है. ऐसा इसलिए होता है, क्योंकि पूरी लाइन का कुल वज़न 1f होता है:

ग्रिड पर आखिरी आइटम का साइज़ फ़ुल साइज़ में दिखेगा
तीसरी इमेज. FlowRow का इस्तेमाल करके, एक ग्रिड बनाना जिसमें आखिरी आइटम पूरी चौड़ाई में हो

वज़न को अन्य Modifiers के साथ जोड़ा जा सकता है. जैसे, Modifier.width(exactDpAmount), Modifier.aspectRatio(aspectRatio) या Modifier.fillMaxWidth(fraction). ये सभी मॉडिफ़ायर एक साथ काम करते हैं, ताकि FlowRow (या FlowColumn) में मौजूद आइटम का साइज़, स्क्रीन के हिसाब से बदला जा सके.

अलग-अलग साइज़ के आइटम का एक ऐसा ग्रिड भी बनाया जा सकता है जिसमें दो आइटम, कॉलम की आधी-आधी चौड़ाई लेते हैं और एक आइटम, अगले कॉलम की पूरी चौड़ाई लेता है:

फ़्लो रो के साथ ऑल्टरनेटिंग ग्रिड
चौथी इमेज. FlowRow, जिसमें पंक्तियों के साइज़ अलग-अलग हैं

इसके लिए, इस कोड का इस्तेमाल करें:

FlowRow(
    modifier = Modifier.padding(4.dp),
    horizontalArrangement = Arrangement.spacedBy(4.dp),
    maxItemsInEachRow = 2
) {
    val itemModifier = Modifier
        .padding(4.dp)
        .height(80.dp)
        .clip(RoundedCornerShape(8.dp))
        .background(Color.Blue)
    repeat(6) { item ->
        // if the item is the third item, don't use weight modifier, but rather fillMaxWidth
        if ((item + 1) % 3 == 0) {
            Spacer(modifier = itemModifier.fillMaxWidth())
        } else {
            Spacer(modifier = itemModifier.weight(0.5f))
        }
    }
}

फ़्रैक्शनल साइज़िंग

Modifier.fillMaxWidth(fraction) का इस्तेमाल करके, उस कंटेनर का साइज़ तय किया जा सकता है जिसमें किसी आइटम को रखा जाना चाहिए. यह Row या Column पर लागू होने पर, Modifier.fillMaxWidth(fraction) के काम करने के तरीके से अलग है. इसमें Row/Column आइटम, पूरे कंटेनर की चौड़ाई के बजाय, बची हुई चौड़ाई का कुछ प्रतिशत हिस्सा लेते हैं.

उदाहरण के लिए, FlowRow और Row का इस्तेमाल करने पर, यहां दिया गया कोड अलग-अलग नतीजे देता है:

FlowRow(
    modifier = Modifier.padding(4.dp),
    horizontalArrangement = Arrangement.spacedBy(4.dp),
    maxItemsInEachRow = 3
) {
    val itemModifier = Modifier
        .clip(RoundedCornerShape(8.dp))
    Box(
        modifier = itemModifier
            .height(200.dp)
            .width(60.dp)
            .background(Color.Red)
    )
    Box(
        modifier = itemModifier
            .height(200.dp)
            .fillMaxWidth(0.7f)
            .background(Color.Blue)
    )
    Box(
        modifier = itemModifier
            .height(200.dp)
            .weight(1f)
            .background(Color.Magenta)
    )
}

FlowRow: बीच का आइटम, जिसकी चौड़ाई पूरे कंटेनर की चौड़ाई का 0.7 हिस्सा है.

फ़्लो रो के साथ फ़्रैक्शनल चौड़ाई

Row: बीच वाला आइटम, Row की बची हुई चौड़ाई का 0.7 प्रतिशत हिस्सा ले रहा है.

लाइन के साथ फ़्रैक्शनल चौड़ाई

fillMaxColumnWidth() और fillMaxRowHeight()

FlowColumn या FlowRow के अंदर मौजूद किसी आइटम पर Modifier.fillMaxColumnWidth() या Modifier.fillMaxRowHeight() लागू करने से, यह पक्का होता है कि एक ही कॉलम या लाइन में मौजूद आइटम की चौड़ाई या ऊंचाई, कॉलम/लाइन में मौजूद सबसे बड़े आइटम के बराबर हो.

उदाहरण के लिए, इस उदाहरण में Android के डेज़र्ट की सूची दिखाने के लिए, FlowColumn का इस्तेमाल किया गया है. हर आइटम की चौड़ाई में अंतर देखा जा सकता है. ऐसा तब होता है, जब आइटम पर Modifier.fillMaxColumnWidth() लागू किया जाता है और जब इसे लागू नहीं किया जाता है और आइटम रैप हो जाते हैं.

FlowColumn(
    Modifier
        .padding(20.dp)
        .fillMaxHeight()
        .fillMaxWidth(),
    horizontalArrangement = Arrangement.spacedBy(8.dp),
    verticalArrangement = Arrangement.spacedBy(8.dp),
    maxItemsInEachColumn = 5,
) {
    repeat(listDesserts.size) {
        Box(
            Modifier
                .fillMaxColumnWidth()
                .border(1.dp, Color.DarkGray, RoundedCornerShape(8.dp))
                .padding(8.dp)
        ) {

            Text(
                text = listDesserts[it],
                fontSize = 18.sp,
                modifier = Modifier.padding(3.dp)
            )
        }
    }
}

हर आइटम पर Modifier.fillMaxColumnWidth() लागू किया गया

fillMaxColumnWidth

चौड़ाई में कोई बदलाव सेट नहीं किया गया (आइटम रैप किए जा रहे हैं)

कॉलम की ज़्यादा से ज़्यादा चौड़ाई सेट नहीं की गई है