چیدمان‌های جاری در Compose

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

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

‫۵ تراشه در «ردیف جاری»، که وقتی فضای بیشتری دردسترس نباشد سرریز را به خط بعدی نشان می‌دهد.
شکل ۱. مثال 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، عناصر به‌صورت افقی چیده می‌شوند). پارامتر 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 باعث می‌شود چیدمان اولیه فقط ۳ مورد داشته باشد:

حداکثری تنظیم نشده است

maxItemsInEachRow = 3

حداکثری برای ردیف جاری‌سازی تنظیم نشده است حداکثر موارد تنظیم‌شده در ردیف جاری‌سازی

وزن‌های مورد

وزن مورد را براساس عامل آن و فضای دردسترس در خطی که در آن قرار گرفته است رشد می‌دهد. نکته مهم این است که بین 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)
    }
}

نکته مهم اینکه اگر مورد دیگری اضافه کنید و آن را به‌جای ۹ بار ۱۰ بار تکرار کنید، مورد آخر کل ستون آخر را پر می‌کند، زیرا وزن کل ردیف 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 درمقایسه با 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: عنصر میانی با ۰٫۷ کسر از کل عرض محتوی.

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

‫Row: مورد میانی ۰٫۷ درصد از پهنای Row باقی‌مانده را اشغال می‌کند.

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

‫fillMaxColumnWidth() و fillMaxRowHeight()

اعمال Modifier.fillMaxColumnWidth() یا Modifier.fillMaxRowHeight() به عنصری در FlowColumn یا FlowRow باعث می‌شود عناصر در همان ستون یا ردیف همان عرض یا ارتفاع را به‌عنوان بزرگ‌ترین عنصر در ستون/ردیف داشته باشند.

برای مثال، این نمونه از FlowColumn برای نمایش فهرست دسرهای Android استفاده می‌کند. وقتی 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() برای هر مورد اعمال شد

پر کردن حداکثر عرض ستون

تغییری در پهنا تنظیم نشده است (پیچیدن موارد)

حداکثر عرض ستون «بدون پر کردن» تنظیم نشده است