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

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

सामान का वज़न

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

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

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

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

फ़्लो रो की मदद से बनाई गई ग्रिड
दूसरी इमेज. 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) का इस्तेमाल करके, उस कंटेनर का साइज़ तय किया जा सकता है जिसमें किसी आइटम को रखना है. Modifier.fillMaxWidth(fraction) को Row या Column पर लागू करने पर, यह सुविधा अलग तरीके से काम करती है. ऐसा इसलिए, क्योंकि Row/Column आइटम, कंटेनर की पूरी चौड़ाई के बजाय, बची हुई चौड़ाई का कुछ हिस्सा लेते हैं.

उदाहरण के लिए, नीचे दिए गए कोड में FlowRow vs 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() लागू होता है, तब हर आइटम की चौड़ाई में क्या अंतर होता है. साथ ही, यह भी दिखाया गया है कि जब आइटम पर 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

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

कॉलम की चौड़ाई को अपने-आप भरने की सुविधा सेट नहीं है