التنسيقات المخصصة

في ميزة "الإنشاء"، يتم تمثيل عناصر واجهة المستخدم من خلال الوظائف القابلة للإنشاء التي تنبعث من جزء من واجهة المستخدم عند استدعاءها، والتي تتم إضافتها بعد ذلك إلى شجرة واجهة المستخدم التي يتم عرضها على الشاشة. ويتضمّن كل عنصر في واجهة المستخدم عنصرًا رئيسيًا واحدًا وربما العديد من العناصر الثانوية. ويتوفر كل عنصر أيضًا داخل العنصر الرئيسي المحدَّد كموضع (x وy) وحجم محدَّد على أنه width وheight.

يحدد الوالدان القيود المفروضة على العناصر الفرعية. ويُطلب من العنصر تحديد حجمه ضمن هذه القيود. تُقيِّد القيود الحد الأدنى والحد الأقصى width للعنصر وheight. إذا كان العنصر يحتوي على عناصر ثانوية، قد يقيس كل عنصر فرعي للمساعدة في تحديد حجمه. بعد أن يحدّد العنصر حجمه ويُبلغ عنه، يصبح بإمكانه تحديد كيفية وضع عناصره الثانوية مقارنةً بنفسها، كما هو موضّح بالتفصيل في إنشاء تنسيقات مخصّصة.

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

  1. قياس مستوى أي أطفال
  2. تحديد حجمه
  3. وضع أطفاله

ثلاث خطوات لتنسيق العُقدة: قياس الأطفال، وتحديد الحجم، ووضع الأطفال

استخدام النطاقات هو الذي يحدّد الحالات التي يمكنك فيها قياس أطفالك ووضعهم في الاعتبار. لا يمكن إجراء قياس إلا أثناء قياسات القياس والتنسيق، ولا يمكن وضع الطفل إلا بعد تمرير تنسيقه (فقط بعد قياسه). بسبب نطاقات الإنشاء، مثل MeasurementScope، وPlacementsScope، يتم فرض ذلك في وقت التجميع.

استخدام معدِّل التنسيق

يمكنك استخدام المُعدِّل "layout" لتعديل كيفية قياس عنصر وتحديده. Layout هي دالة lambda، وتتضمّن معلَماتها العنصر الذي يمكنك قياسه، وتم تمريره على أنّه measurable، والقيود التي تظهر على الموقع قابلة للإنشاء، والتي يتم ضبطها على أنها constraints. يمكن أن يبدو مُعدِّل التنسيق المخصص على النحو التالي:

fun Modifier.customLayoutModifier() =
    layout { measurable, constraints ->
        // ...
    }

لنعرِض Text على الشاشة ونتحكّم في المسافة من أعلى السطر إلى سطر السطر الأول من النص. هذه هي بالضبط الطريقة التي ينفّذ بها معدِّل paddingFromBaseline، ويتم تنفيذه هنا كمثال. لإجراء ذلك، استخدِم المُعدِّل layout لوضع العناصر القابلة للإنشاء يدويًا على الشاشة. إليك السلوك الذي تم فيه ضبط المساحة المتروكة في Text الأعلى على 24.dp:

يعرض الفرق بين المساحة المتروكة العادية في واجهة المستخدم، والتي تُحدِّد المسافة بين العناصر والمساحات المتروكة للنص الذي يضبط المساحة من مرجع أساسي إلى آخر.

إليك الرمز الذي ينتج عن ذلك التباعد:

fun Modifier.firstBaselineToTop(
    firstBaselineToTop: Dp
) = layout { measurable, constraints ->
    // Measure the composable
    val placeable = measurable.measure(constraints)

    // Check the composable has a first baseline
    check(placeable[FirstBaseline] != AlignmentLine.Unspecified)
    val firstBaseline = placeable[FirstBaseline]

    // Height of the composable with padding - first baseline
    val placeableY = firstBaselineToTop.roundToPx() - firstBaseline
    val height = placeable.height + placeableY
    layout(placeable.width, height) {
        // Where the composable gets placed
        placeable.placeRelative(0, placeableY)
    }
}

إليك ما يحدث في هذا الرمز:

  1. في مَعلمة lambda في measurable، يمكنك قياس المعلَمة Text الممثَّلة بواسطة المَعلمة القابلة للقياس عن طريق استدعاء measurable.measure(constraints).
  2. ويمكنك تحديد حجم العنصر القابل للإنشاء من خلال استدعاء الطريقة layout(width, height) التي توفّر دالة lambda المُستخدَمة لوضع العناصر الملفوفة. وفي هذه الحالة، تكون القيمة هي الارتفاع بين القاعدة المرجعية الأخيرة وأكبر مساحة متروكة.
  3. يمكنك وضع العناصر الملفوفة على الشاشة من خلال الاتصال placeable.place(x, y). إذا لم يتم وضع العناصر الملفوفة، لن تكون مرئية. يتوافق yالموضع مع المساحة المتروكة العليا، وهي موضع الخط المرجعي الأول للنص.

للتأكد من أنّ هذه العملية تعمل على النحو المتوقّع، استخدِم أداة التعديل هذه على Text:

@Preview
@Composable
fun TextWithPaddingToBaselinePreview() {
    MyApplicationTheme {
        Text("Hi there!", Modifier.firstBaselineToTop(32.dp))
    }
}

@Preview
@Composable
fun TextWithNormalPaddingPreview() {
    MyApplicationTheme {
        Text("Hi there!", Modifier.padding(top = 32.dp))
    }
}

النُسخ المتعددة من العناصر النصية: يعرض أحدها المساحة المتروكة العادية بين العناصر، ويعرض الآخر المساحة المتروكة من خط مرجعي إلى آخر

إنشاء تنسيقات مخصّصة

لا يغيّر معدِّل layout سوى المكالمات القابلة للإنشاء. لقياس وتعديل عدة تركيبات، يمكنك استخدام السمة Layout القابلة للإنشاء. ويسمح لك ذلك القابل للإنشاء بقياس الأطفال وتحديدهم يدويًا. تم تصميم جميع التنسيقات ذات المستوى الأعلى، مثل Column وRow، بشكل قابل للدمج مع Layout.

لننشئ إصدارًا أساسيًا من Column. تتبع معظم التنسيقات المخصصة هذا النمط:

@Composable
fun MyBasicColumn(
    modifier: Modifier = Modifier,
    content: @Composable () -> Unit
) {
    Layout(
        modifier = modifier,
        content = content
    ) { measurables, constraints ->
        // measure and position children given constraints logic here
        // ...
    }
}

على غرار المُعدِّل layout، تمثل measurables قائمة العناصر الثانوية التي يجب قياسها وconstraints هي القيود المفروضة من العنصر الرئيسي. باتّباع المنطق نفسه كما في السابق، يمكن تنفيذ MyBasicColumn على النحو التالي:

@Composable
fun MyBasicColumn(
    modifier: Modifier = Modifier,
    content: @Composable () -> Unit
) {
    Layout(
        modifier = modifier,
        content = content
    ) { measurables, constraints ->
        // Don't constrain child views further, measure them with given constraints
        // List of measured children
        val placeables = measurables.map { measurable ->
            // Measure each children
            measurable.measure(constraints)
        }

        // Set the size of the layout as big as it can
        layout(constraints.maxWidth, constraints.maxHeight) {
            // Track the y co-ord we have placed children up to
            var yPosition = 0

            // Place children in the parent layout
            placeables.forEach { placeable ->
                // Position item on the screen
                placeable.placeRelative(x = 0, y = yPosition)

                // Record the y co-ord placed up to
                yPosition += placeable.height
            }
        }
    }
}

تخضع العناصر القابلة للإنشاء الفرعية للقيود Layout (بدون قيود minHeight) ويتم وضعها استنادًا إلى yPosition للتركيبة السابقة.

في ما يلي كيفية استخدام الصيغة القابلة للإنشاء المخصّصة:

@Composable
fun CallingComposable(modifier: Modifier = Modifier) {
    MyBasicColumn(modifier.padding(8.dp)) {
        Text("MyBasicColumn")
        Text("places items")
        Text("vertically.")
        Text("We've done it by hand!")
    }
}

عدّة عناصر نصية مكدّسة فوق الجزء التالي في العمود

اتجاه التنسيق

يمكنك تغيير اتجاه التنسيق للإنشاء من خلال تغيير مقطوعة LocalLayoutDirection المحلية.

في حال وضع عناصر قابلة للإنشاء يدويًا على الشاشة، تُعدّ LayoutDirection جزءًا من LayoutScope المعدِّل layout أو Layout القابل للإنشاء.

عند استخدام layoutDirection، يمكنك وضع العناصر القابلة للإنشاء باستخدام place. وعلى عكس الطريقة placeRelative، لا تتغير place بناءً على اتجاه التنسيق (من اليسار إلى اليمين أو من اليمين إلى اليسار).

التنسيقات المخصصة قيد الاستخدام

تعرَّف على مزيد من المعلومات عن التنسيقات والمعدِّلات في التنسيقات الأساسية في Compose، واطّلِع على كيفية استخدام التنسيقات المخصّصة في إنشاء النماذج التي تنشئ تنسيقات مخصّصة.

مزيد من المعلومات

لمعرفة المزيد من المعلومات عن التنسيقات المخصصة في ميزة "الإنشاء"، يُرجى الاطّلاع على المراجع الإضافية التالية.

الفيديوهات الطويلة