يتيح لك نموذج تصميم Compose استخدام AlignmentLine لإنشاء خطوط محاذاة مخصّصة يمكن استخدامها في تصميمات العناصر الرئيسية لمحاذاة العناصر الفرعية وتحديد موضعها. على سبيل المثال، يمكن أن يستخدم Row خطوط المحاذاة المخصّصة للعناصر الفرعية
لمحاذاتها.
عندما يوفّر التنسيق قيمة لسمة AlignmentLine معيّنة، يمكن للعناصر الرئيسية للتنسيق قراءة هذه القيمة بعد القياس، وذلك باستخدام عامل التشغيل Placeable.get في مثيل Placeable المقابل. استنادًا إلى موضع AlignmentLine، يمكن للوالدَين تحديد موضع الأطفال.
تتضمّن بعض الدوال المركّبة في Compose خطوط محاذاة. على سبيل المثال، تعرض الدالة المركّبة BasicText خطوط المحاذاة FirstBaseline وLastBaseline.
في المثال التالي، يقرأ عنصر LayoutModifier مخصّص باسم
firstBaselineToTop السمة FirstBaseline لإضافة مساحة متروكة إلى Text
بدءًا من خط الأساس الأول.
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 تعرض خطَّي محاذاة، هما MaxChartValue وMinChartValue، لكي تتمكّن الدوال المركّبة الأخرى من المحاذاة مع الحد الأقصى والحد الأدنى لقيمة البيانات في الرسم البياني. تمت محاذاة عنصرَي نص، هما الحد الأقصى والحد الأدنى، إلى منتصف خطوط المحاذاة المخصّصة.
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، لأنّها
تُستخدَم لمحاذاة العناصر الثانوية عموديًا. يتم تمرير سياسة الدمج كمَعلمة في حال توفير عدة تصاميم قيمة لخطوط المحاذاة هذه. بما أنّ إحداثيات نظام تنسيق Compose وإحداثيات 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() ) ) {} } } } } }
يمكن للعناصر الرئيسية المباشرة وغير المباشرة لهذه الدالة المركّبة استخدام خطوط
المحاذاة. تنشئ الدالة المركّبة التالية تنسيقًا مخصّصًا يأخذ كمعلمة خانتَين من النوع 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 غير مفعَّل
- الرسومات في Compose
- التنسيقات المخصّصة {:#custom-layouts }
- القياسات الجوهرية في تنسيقات Compose