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

‫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)

عناصر متباعدة بمقدار معيّن من وحدات البكسل المستقلة عن الكثافة

بالنسبة إلى 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

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

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