מודל הפריסה של Compose מאפשר להשתמש ב-AlignmentLine
כדי ליצור קווים מותאמים אישית של יישור, שפריסות הורה יכולות להשתמש בהם כדי ליישר ולמקם את הפריסות הצאצאיות. לדוגמה, אפשר להשתמש בקווי ההתאמה המותאמים אישית של הצאצאים של Row
כדי ליישר אותם.
כשפריסה מספקת ערך ל-AlignmentLine
מסוים, ההורים של הפריסה יכולים לקרוא את הערך הזה אחרי המדידה, באמצעות האופרטור Placeable.get
במכונה המתאימה של Placeable
.
על סמך המיקום של AlignmentLine
, ההורים יכולים להחליט איך למקם את הילדים.
חלק מהרכיבים הניתנים לשילוב ב-Compose כבר מגיעים עם קווים ליישור. לדוגמה, הרכיב הניתן לקיבוץ 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
בהתאמה אישית שמוצגים בו שני קווים של התאמה, MaxChartValue
ו-MinChartValue
, כדי שרכיבים מותאמים אחרים יוכלו להתאים לערך הנתונים המקסימלי והמינימלי בתרשים. שני רכיבי טקסט, Max ו-Min, הותאמו למרכז של קווים מותאמים אישית ליישור.
איור 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
, כי הם משמשים ליישור צאצאים אנכית. מדיניות המיזוג מועברת כפרמטר למקרה שמספר פריסות מספקות ערך לקווי ההתאמה האלה. מכיוון שהקואורדינטות של מערכת הפריסה של 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