تنسيقات التدفق في "إنشاء"

FlowRow وFlowColumn هما دالتان إنشائيتان تشبهان Row وColumn، ولكنّهما تختلفان في أنّ العناصر تنتقل إلى السطر التالي عندما تنتهي المساحة في الحاوية. ويؤدي ذلك إلى إنشاء صفوف أو أعمدة متعدّدة. يمكن أيضًا التحكّم في عدد العناصر في السطر من خلال ضبط maxItemsInEachRow أو maxItemsInEachColumn. يمكنك غالبًا استخدام FlowRow وFlowColumn لإنشاء تنسيقات متجاوبة، ولن يتم قطع المحتوى إذا كانت العناصر كبيرة جدًا بالنسبة إلى أحد الأبعاد، ويمكن أن يساعد استخدام مجموعة من maxItemsInEach* مع Modifier.weight(weight) في إنشاء تنسيقات تملأ عرض الصف أو العمود أو توسّعهما عند الحاجة.

المثال النموذجي هو واجهة مستخدم للرقائق أو الفلترة:

5 شرائح في FlowRow، تعرض الفائض في السطر التالي عندما لا تتوفّر مساحة إضافية.
الشكل 1. مثال على 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 إلى فرض أن يحتوي التنسيق الأولي على 3 عناصر فقط:

لم يتم ضبط الحد الأقصى

maxItemsInEachRow = 3

لم يتم ضبط حدّ أقصى لعدد الصفوف في التدفق الحدّ الأقصى للعناصر المضبوطة في صف التدفق

أوزان العناصر

يزيد الوزن حجم العنصر استنادًا إلى عامله والمساحة المتاحة في السطر الذي تم وضعه فيه. من المهم ملاحظة أنّ هناك فرقًا بين FlowRow وRow في طريقة استخدام الأوزان لحساب عرض العنصر. بالنسبة إلى Rows، يستند الوزن إلى جميع العناصر في الـ Row. بالنسبة إلى FlowRow، يستند الوزن إلى العناصر في السطر الذي تم وضع العنصر فيه، وليس جميع العناصر في حاوية FlowRow.

على سبيل المثال، إذا كان لديك 4 عناصر تظهر جميعها في سطر واحد، وكان لكل منها أوزان مختلفة هي 1f, 2f, 1f و3f، فإنّ الوزن الإجمالي هو 7f. سيتم تقسيم المساحة المتبقية في الصف أو العمود على 7f. بعد ذلك، سيتم حساب عرض كل عنصر باستخدام: weight * (remainingSpace / totalWeight).

يمكنك استخدام مجموعة من Modifier.weight والحد الأقصى لعدد العناصر مع FlowRow أو FlowColumn لإنشاء تنسيق يشبه الشبكة. هذا النهج مفيد لإنشاء تنسيقات متجاوبة تتكيّف مع حجم جهازك.

هناك بعض الأمثلة المختلفة على ما يمكنك تحقيقه باستخدام الأوزان. أحد الأمثلة هو شبكة تكون فيها العناصر متساوية الحجم، كما هو موضّح أدناه:

تم إنشاء شبكة باستخدام صف التدفق
الشكل 2. استخدام 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 مرات بدلاً من 9، سيشغل العنصر الأخير العمود الأخير بالكامل، لأنّ الوزن الإجمالي للصف بأكمله هو 1f:

حجم العنصر الأخير الكامل في الشبكة
الشكل 3. استخدام FlowRow لإنشاء شبكة يشغل فيها العنصر الأخير العرض الكامل

يمكنك دمج الأوزان مع Modifiers أخرى، مثل Modifier.width(exactDpAmount), Modifier.aspectRatio(aspectRatio) أو Modifier.fillMaxWidth(fraction). تعمل كل هذه المعدِّلات معًا للسماح بتغيير حجم العناصر بشكل متجاوب داخل FlowRow (أو FlowColumn).

يمكنك أيضًا إنشاء شبكة متناوبة بأحجام مختلفة للعناصر، حيث يشغل عنصران نصف العرض لكل منهما، ويشغل عنصر واحد العرض الكامل للعمود التالي:

شبكة متناوبة مع صف انسيابي
الشكل 4. 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 لعرض قائمة حلويات 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() مطبّق على كل عنصر

fillMaxColumnWidth

لم يتم ضبط أي تغييرات في العرض (انتقال العناصر إلى سطر جديد)

لم يتم ضبط الحدّ الأقصى لعرض عمود التعبئة