جریان طرح‌بندی‌ها در Compose

FlowRow و FlowColumn ترکیب‌هایی هستند که شبیه به Row و Column هستند، اما از این نظر تفاوت دارند که وقتی فضای ظرف تمام می‌شود، آیتم‌ها در خط بعدی جریان پیدا می‌کنند. این باعث ایجاد چندین ردیف یا ستون می شود. با تنظیم maxItemsInEachRow یا maxItemsInEachColumn نیز می توان تعداد موارد در یک خط را کنترل کرد. اغلب می‌توانید از FlowRow و FlowColumn برای ایجاد طرح‌بندی‌های واکنش‌گرا استفاده کنید - اگر موارد برای یک بعد خیلی بزرگ باشند، محتوا قطع نمی‌شود، و استفاده از ترکیب maxItemsInEach* با Modifier.weight(weight) می‌تواند به ساخت طرح‌بندی‌هایی کمک کند که صفحه‌بندی را پر/بسط می‌دهند. عرض یک سطر یا ستون در صورت نیاز.

مثال معمولی برای تراشه یا رابط کاربری فیلتر است:

5 تراشه در یک FlowRow که سرریز را به خط بعدی نشان می دهد که فضای بیشتری در دسترس نباشد.
شکل 1. مثالی از FlowRow

استفاده اساسی

برای استفاده از FlowRow یا FlowColumn ، این composable ها را ایجاد کنید و آیتم هایی را در داخل آن قرار دهید که باید از جریان استاندارد پیروی کنند:

@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 ، آیتم ها به صورت افقی چیده می شوند). پارامتر horizontalArrangement در FlowRow نحوه توزیع فضای آزاد بین آیتم ها را کنترل می کند.

جدول زیر نمونه هایی از تنظیم horizontalArrangement بر روی آیتم ها برای FlowRow را نشان می دهد:

چیدمان افقی روی FlowRow تنظیم شده است

نتیجه

Arrangement.Start ( Default )

موارد مرتب شده با شروع

Arrangement.SpaceBetween

چیدمان اقلام با فضای بین

Arrangement.Center

موارد چیده شده در مرکز

Arrangement.End

موارد در پایان مرتب شده است

Arrangement.SpaceAround

اقلام با فضای اطراف مرتب شده اند

Arrangement.spacedBy(8.dp)

اقلام با یک dp مشخص فاصله دارند

برای FlowColumn ، گزینه های مشابه با verticalArrangement با پیش فرض Arrangement.Top موجود است.

آرایش محوری متقاطع

محور متقاطع محوری است در جهت مخالف محور اصلی. به عنوان مثال، در FlowRow ، این محور عمودی است. برای تغییر نحوه چیدمان کلی محتویات داخل ظرف در محور متقاطع، از verticalArrangement برای FlowRow و 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 طرح اولیه را مجبور می کند که فقط 3 مورد داشته باشد:

بدون تنظیم حداکثر

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")
}

نمونه ای از ردیف های جریان متنی.
شکل 2. مثالی از ContextualFlowRow

وزن اقلام

وزن یک آیتم FlowRow بر اساس فاکتور آن و فضای موجود روی خطی Row در آن قرار داده شده است رشد می‌دهد. برای Rows ، وزن بر اساس همه موارد موجود در Row است. با FlowRow ، وزن بر اساس موارد موجود در خطی است که یک آیتم در آن قرار می‌گیرد ، نه همه موارد موجود در ظرف FlowRow .

به عنوان مثال، اگر 4 مورد دارید که همگی روی یک خط قرار می‌گیرند، هر کدام با وزن‌های مختلف 1f, 2f, 1f و 3f ، وزن کل 7f است. فضای باقی مانده در یک سطر یا ستون به 7f تقسیم می شود. سپس، عرض هر مورد با استفاده از: weight * (remainingSpace / totalWeight) محاسبه می شود.

می‌توانید از ترکیبی از آیتم‌های Modifier.weight و max با FlowRow یا FlowColumn برای ایجاد طرح‌بندی شبکه‌ای استفاده کنید. این رویکرد برای ایجاد طرح‌بندی‌های واکنش‌گرا که با اندازه دستگاه شما تنظیم می‌شوند مفید است.

چند مثال مختلف از آنچه می توانید با استفاده از وزنه به دست آورید وجود دارد. یک مثال شبکه‌ای است که در آن آیتم‌ها به اندازه یکسان هستند، همانطور که در زیر نشان داده شده است:

شبکه ایجاد شده با ردیف جریان
شکل 3. استفاده از 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 است:

آخرین مورد در اندازه کامل در شبکه
شکل 4. استفاده از FlowRow برای ایجاد یک شبکه با آخرین مورد که عرض کامل را اشغال می کند

می توانید وزن ها را با Modifiers دیگر مانند Modifier.width(exactDpAmount), Modifier.aspectRatio(aspectRatio) یا Modifier.fillMaxWidth(fraction) ترکیب کنید. این اصلاح‌کننده‌ها همگی با هم کار می‌کنند تا امکان اندازه‌گیری پاسخگوی آیتم‌ها در یک FlowRow (یا FlowColumn ) را فراهم کنند.

همچنین می‌توانید یک شبکه متناوب با اندازه‌های آیتم‌های مختلف ایجاد کنید، که در آن دو آیتم نیمی از عرض هر کدام و یک مورد تمام عرض ستون بعدی را اشغال می‌کند:

شبکه متناوب با ردیف جریان
شکل 5. 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 در مقابل 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 : مورد میانی 0.7 درصد از عرض Row باقی مانده را اشغال می کند.

عرض کسری با ردیف

fillMaxColumnWidth() و fillMaxRowHeight()

اعمال Modifier.fillMaxColumnWidth() یا Modifier.fillMaxRowHeight() بر روی یک آیتم در داخل یک FlowColumn یا FlowRow تضمین می کند که موارد در همان ستون یا سطر همان عرض یا ارتفاع را با بزرگترین آیتم در ستون/ردیف می گیرند.

برای مثال در این مثال از 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

بدون تغییر عرض تنظیم شد (اقلام بسته بندی)

حداکثر عرض ستون پر تنظیم نشده است
{% کلمه به کلمه %} {% آخر کلمه %} {% کلمه به کلمه %} {% آخر کلمه %}