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

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

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

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

این قطعه کد منجر به رابط کاربری نشان داده شده در بالا می‌شود که در آن، وقتی دیگر در ردیف اول جایی وجود نداشته باشد، آیتم‌ها به طور خودکار به ردیف بعدی می‌روند.

ویژگی‌های طرح جریان

طرح‌بندی‌های جریان (Flow layouts) ویژگی‌ها و مشخصه‌های زیر را دارند که می‌توانید از آنها برای ایجاد طرح‌بندی‌های مختلف در برنامه خود استفاده کنید.

چیدمان محور اصلی: چیدمان افقی یا عمودی

محور اصلی، محوری است که آیتم‌ها روی آن قرار می‌گیرند (برای مثال، در 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 و max items به همراه 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 : مورد میانی 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

هیچ تغییر عرضی تنظیم نشده است (بسته‌بندی آیتم‌ها)

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