מודל הפריסה של 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 בהתאמה אישית, מציינים קווי יישור בהתאמה אישית ב-method 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