מודל הפריסה של כתיבת קומפוזיציה מאפשר לכם להשתמש ב-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, כדי שקומפוזבלים אחרים יוכלו להתיישר לפי ערך הנתונים המקסימלי והמינימלי של התרשים. שני רכיבי טקסט, Max ו-Min, מיושרים למרכז של קווי היישור המותאמים אישית.
BarChart composable with Text aligned to the maximum and
minimum data value.קווי יישור מותאמים אישית מוגדרים כמשתנים ברמה העליונה בפרויקט.
/** * 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() ) ) {} } } } } }
ההורים הישירים והעקיפים של הרכיב הזה יכולים להשתמש בקווי היישור. הקומפוזיציה הבאה יוצרת פריסה בהתאמה אישית שמקבלת כפרמטר שני 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