يتيح لك نموذج تنسيق الإنشاء استخدام AlignmentLine
لإنشاء خطوط محاذاة مخصّصة يمكن أن تستخدمها التنسيقات الرئيسية لمحاذاة التنسيقات الفرعية وتحديد مواضعها. على سبيل المثال، يمكن لعنصر
Row
استخدام خطوط المحاذاة المخصّصة لعناصره الفرعية لمحاذاتها.
عندما يقدّم تنسيق قيمة لعنصر AlignmentLine
معيّن، يمكن للعناصر
الرئيسية للتنسيق قراءة هذه القيمة بعد القياس، باستخدام عامل التشغيل Placeable.get
في مثيل
Placeable
المقابل.
استنادًا إلى موضع AlignmentLine
، يمكن للوالدَين
تحديد موضع الأطفال بعد ذلك.
تتضمّن بعض العناصر القابلة للتجميع في ميزة "الإنشاء" خطوط محاذاة. على سبيل المثال، يعرِض العنصر القابل للتجميع
BasicText
خطَّي المحاذاة FirstBaseline
وLastBaseline
.
في المثال أدناه، يقرأ LayoutModifier
مخصّص يُسمى
firstBaselineToTop
FirstBaseline
لإضافة مساحة فارغة إلى Text
بدءًا من خط الأساس الأول.
الشكل 1: يعرض هذا المثال الفرق بين إضافة مسافة بادئة عادية إلى عنصر، وتطبيق مسافة بادئة على خط أساس عنصر نص.
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) } } @Preview @Composable private fun TextWithPaddingToBaseline() { MaterialTheme { Text("Hi there!", Modifier.firstBaselineToTop(32.dp)) } }
لقراءة FirstBaseline
في المثال،
يتم استخدام placeable [FirstBaseline]
في مرحلة القياس.
إنشاء خطوط محاذاة مخصّصة
عند إنشاء عنصر Layout
مكوّن مخصّص أو عنصر LayoutModifier
مخصّص، يمكنك توفير
خطوط محاذاة مخصّصة حتى تتمكّن العناصر المكوّنة الرئيسية الأخرى من استخدامها لمحاذاة
عناصرها الفرعية وتحديد مواضعها وفقًا لذلك.
يعرض المثال التالي عنصرًا مكوّنًا مخصّصًا من النوع BarChart
يعرض خطَّي ALIGNED، MaxChartValue
وMinChartValue
، لكي تتمكّن العناصر المكوّنة الأخرى من ALIGNED من المحاذاة مع الحد الأقصى والحد الأدنى لقيمة البيانات في الرسم البياني. تمّت محاذاة عنصرَي النص
الحدّ الأقصى والحدّ الأدنى في منتصف خطوط المحاذاة
المخصّصة.
الشكل 2: BarChart
قابلة للتجميع مع النص الذي تمّت محاذاته مع الحدّ الأقصى
والحدّ الأدنى لقيمة البيانات.
يتم تعريف خطوط المحاذاة المخصّصة على أنّها متغيّرات من المستوى الأعلى في مشروعك.
/** * AlignmentLine defined by the maximum data value in a [BarChart] */ private val MaxChartValue = HorizontalAlignmentLine(merger = { old, new -> min(old, new) }) /** * AlignmentLine defined by the minimum data value in a [BarChart] */ private val MinChartValue = HorizontalAlignmentLine(merger = { old, new -> max(old, new) })
تكون خطوط المحاذاة المخصّصة لإنشاء المثال من النوع
HorizontalAlignmentLine
، لأنّه
يُستخدَم هذا النوع لمحاذاة العناصر الفرعية عموديًا. يتم تمرير سياسة الدمج كمَعلمة
في حال تقديم تنسيقات متعددة لقيمة خطوط المحاذاة هذه. بما أنّ
إحداثيات نظام تنسيق "الإنشاء" وإحداثيات Canvas
تمثّل [0, 0]
، يكون الزاوية العلوية اليسرى والمحوران x
وy
موجبَين للأسفل، لذا ستكون قيمة MaxChartValue
دائمًا أصغر من
MinChartValue
. وبالتالي، تكون سياسة الدمج هي min
لقاعدة بيانات
الرسم البياني القصوى وmax
لقاعدة بيانات الرسم البياني الدنيا.
عند إنشاء Layout
أو LayoutModifier
مخصّصَين، حدِّد خطوط محاذاة
مخصّصة في طريقة MeasureScope.layout
التي تأخذ مَعلمة alignmentLines: Map<AlignmentLine, Int>
.
@Composable private fun BarChart( dataPoints: List<Int>, modifier: Modifier = Modifier, ) { val maxValue: Float = remember(dataPoints) { dataPoints.maxOrNull()!! * 1.2f } BoxWithConstraints(modifier = modifier) { val density = LocalDensity.current with(density) { // ... // Calculate baselines val maxYBaseline = // ... val minYBaseline = // ... Layout( content = {}, modifier = Modifier.drawBehind { // ... } ) { _, constraints -> with(constraints) { layout( width = if (hasBoundedWidth) maxWidth else minWidth, height = if (hasBoundedHeight) maxHeight else minHeight, // Custom AlignmentLines are set here. These are propagated // to direct and indirect parent composables. alignmentLines = mapOf( MinChartValue to minYBaseline.roundToInt(), MaxChartValue to maxYBaseline.roundToInt() ) ) {} } } } } }
يمكن للعناصر المباشرة وغير المباشرة التي تتضمّن هذا العنصر القابل للتجميع استخدام خطوط alignment. ينشئ العنصر القابل للتجميع التالي تنسيقًا مخصّصًا يستخدِم
مَعلمتَين هما خانتَا Text
ونقطةَا بيانات، وينسِّق النصَين مع
الحد الأقصى والحد الأدنى لقيم بيانات الرسم البياني. المعاينة لهذا العنصر القابل للتجميع هي
ما هو موضّح في الشكل 2.
@Composable private fun BarChartMinMax( dataPoints: List<Int>, maxText: @Composable () -> Unit, minText: @Composable () -> Unit, modifier: Modifier = Modifier, ) { Layout( content = { maxText() minText() // Set a fixed size to make the example easier to follow BarChart(dataPoints, Modifier.size(200.dp)) }, modifier = modifier ) { measurables, constraints -> check(measurables.size == 3) val placeables = measurables.map { it.measure(constraints.copy(minWidth = 0, minHeight = 0)) } val maxTextPlaceable = placeables[0] val minTextPlaceable = placeables[1] val barChartPlaceable = placeables[2] // Obtain the alignment lines from BarChart to position the Text val minValueBaseline = barChartPlaceable[MinChartValue] val maxValueBaseline = barChartPlaceable[MaxChartValue] layout(constraints.maxWidth, constraints.maxHeight) { maxTextPlaceable.placeRelative( x = 0, y = maxValueBaseline - (maxTextPlaceable.height / 2) ) minTextPlaceable.placeRelative( x = 0, y = minValueBaseline - (minTextPlaceable.height / 2) ) barChartPlaceable.placeRelative( x = max(maxTextPlaceable.width, minTextPlaceable.width) + 20, y = 0 ) } } } @Preview @Composable private fun ChartDataPreview() { MaterialTheme { BarChartMinMax( dataPoints = listOf(4, 24, 15), maxText = { Text("Max") }, minText = { Text("Min") }, modifier = Modifier.padding(24.dp) ) } }
أفلام مُقترَحة لك
- ملاحظة: يتم عرض نص الرابط عندما تكون لغة JavaScript غير مفعّلة.
- الرسومات في ميزة "إنشاء"
- التنسيقات المخصّصة {:#custom-layouts }
- القياسات الأساسية في تنسيقات ميزة "الإنشاء"