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

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

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

FlowRow में 5 चिप मौजूद होते हैं. कोई लाइन न होने पर, अगली लाइन पर ओवरफ़्लो दिखाया जाता है
ज़्यादा जगह उपलब्ध है.
पहली इमेज. 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 पैरामीटर, आइटम के बीच खाली जगह के बंटवारे के तरीके को कंट्रोल करता है.

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

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

नतीजा

Arrangement.Start (Default)

शुरुआत के साथ क्रम से लगाए गए आइटम

Arrangement.SpaceBetween

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

Arrangement.Center

बीच में व्यवस्थित किए गए आइटम

Arrangement.End

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

Arrangement.SpaceAround

आइटम के आस-पास खाली जगह है

Arrangement.spacedBy(8.dp)

किसी खास डीपी के हिसाब से आइटम में स्पेस

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

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

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

नीचे दी गई टेबल में, 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

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

फ़्लो आइटम की लेज़ी लोडिंग

ContextualFlowRow और ContextualFlowColumn, FlowRow और FlowColumn के खास वर्शन हैं. इनकी मदद से, फ़्लो की पंक्ति या कॉलम के कॉन्टेंट को धीरे-धीरे लोड किया जा सकता है. वे आइटम की स्थिति की जानकारी भी देते हैं (इंडेक्स, लाइन की संख्या, और उपलब्ध साइज़), जैसे कि अगर आइटम पहले लाइन. यह बड़े डेटा-सेट के लिए और काम की जानकारी की ज़रूरत होने पर काम आता है किसी आइटम के बारे में जानकारी.

maxLines पैरामीटर, दिखाई जाने वाली पंक्तियों की संख्या को सीमित करता है. साथ ही, overflow पैरामीटर यह तय करता है कि आइटम की संख्या तय सीमा से ज़्यादा होने पर क्या दिखाया जाए. इसके लिए, आपके पास कस्टम expandIndicator या collapseIndicator तय करने का विकल्प होता है.

उदाहरण के लिए, "+ (बचे हुए आइटम की संख्या)" दिखाने के लिए या "कम दिखाएं" बटन:

val totalCount = 40
var maxLines by remember {
    mutableStateOf(2)
}

val moreOrCollapseIndicator = @Composable { scope: ContextualFlowRowOverflowScope ->
    val remainingItems = totalCount - scope.shownItemCount
    ChipItem(if (remainingItems == 0) "Less" else "+$remainingItems", onClick = {
        if (remainingItems == 0) {
            maxLines = 2
        } else {
            maxLines += 5
        }
    })
}
ContextualFlowRow(
    modifier = Modifier
        .safeDrawingPadding()
        .fillMaxWidth(1f)
        .padding(16.dp)
        .wrapContentHeight(align = Alignment.Top)
        .verticalScroll(rememberScrollState()),
    verticalArrangement = Arrangement.spacedBy(4.dp),
    horizontalArrangement = Arrangement.spacedBy(8.dp),
    maxLines = maxLines,
    overflow = ContextualFlowRowOverflow.expandOrCollapseIndicator(
        minRowsToShowCollapse = 4,
        expandIndicator = moreOrCollapseIndicator,
        collapseIndicator = moreOrCollapseIndicator
    ),
    itemCount = totalCount
) { index ->
    ChipItem("Item $index")
}

कॉन्टेक्स्ट के हिसाब से फ़्लो की लाइनों का उदाहरण.
दूसरी इमेज. ContextualFlowRow का उदाहरण

आइटम का वज़न

किसी आइटम का वज़न, उसके फ़ैक्टर और लाइन में मौजूद जगह के आधार पर बढ़ता है को अंदर रखा गया. अहम बात यह है कि 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)
    }
}

अहम बात यह है कि अगर आप कोई दूसरा आइटम जोड़ते हैं और उसे 9 के बजाय 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()

Modifier.fillMaxColumnWidth() को लागू किया जा रहा है या FlowColumn या FlowRow में मौजूद किसी आइटम पर 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() हर आइटम पर लागू किया गया

फ़िलमैक्स कॉलम की चौड़ाई

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

कॉलम की ज़्यादा से ज़्यादा चौड़ाई भरने की सुविधा सेट नहीं है