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

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

لم يتم ضبط أي تغييرات في العرض (تغليف العناصر)

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