Im Layoutmodell „Compose“ können Sie mit AlignmentLine
benutzerdefinierte Ausrichtungslinien erstellen, die von übergeordneten Layouts zum Ausrichten und Positionieren von untergeordneten Layouts verwendet werden können. Beispielsweise kann Row
die benutzerdefinierten Ausrichtungslinien seiner untergeordneten Elemente verwenden, um sie auszurichten.
Wenn ein Layout einen Wert für eine bestimmte AlignmentLine
bereitstellt, können die übergeordneten Elemente des Layouts diesen Wert nach der Messung mithilfe des Operators Placeable.get
in der entsprechenden Placeable
-Instanz lesen.
Anhand der Position von AlignmentLine
können die Eltern dann die Position der untergeordneten Elemente festlegen.
Einige zusammensetzbare Funktionen in der Funktion „Compose“ enthalten bereits Ausrichtungslinien. Die zusammensetzbare Funktion BasicText
macht beispielsweise die Ausrichtungslinien FirstBaseline
und LastBaseline
verfügbar.
Im folgenden Beispiel liest ein benutzerdefiniertes LayoutModifier
namens firstBaselineToTop
FirstBaseline
, um dem Text
ausgehend von seiner ersten Referenz einen Innenabstand hinzuzufügen.
Abbildung 1: Zeigt den Unterschied zwischen dem Hinzufügen eines normalen Abstands zu einem Element und dem Anwenden eines Abstands auf die Referenz eines Textelements.
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)) } }
Zum Lesen von FirstBaseline
im Beispiel wird placeable [FirstBaseline]
in der Messphase verwendet.
Benutzerdefinierte Ausrichtungslinien erstellen
Wenn Sie eine benutzerdefinierte zusammensetzbare Funktion Layout
oder eine benutzerdefinierte LayoutModifier
erstellen, können Sie benutzerdefinierte Ausrichtungslinien angeben, damit andere übergeordnete zusammensetzbare Funktionen diese verwenden können, um ihre untergeordneten Elemente entsprechend auszurichten und zu positionieren.
Das folgende Beispiel zeigt eine benutzerdefinierte zusammensetzbare Funktion BarChart
mit zwei Ausrichtungslinien, MaxChartValue
und MinChartValue
, damit andere zusammensetzbare Funktionen an den maximalen und minimalen Datenwert des Diagramms ausgerichtet werden können. Die beiden Textelemente Max und Min wurden an der Mitte der benutzerdefinierten Ausrichtungslinien ausgerichtet.
Abbildung 2: BarChart
zusammensetzbar mit Text, der auf den maximalen und minimalen Datenwert ausgerichtet ist.
Benutzerdefinierte Ausrichtungslinien werden in Ihrem Projekt als Variablen der obersten Ebene definiert.
/** * 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) })
Die benutzerdefinierten Ausrichtungslinien in unserem Beispiel sind vom Typ HorizontalAlignmentLine
, da damit untergeordnete Elemente vertikal ausgerichtet werden. Eine Zusammenführungsrichtlinie wird als Parameter übergeben, wenn mehrere Layouts einen Wert für diese Ausrichtungslinien bereitstellen. Da die Koordinaten des Layoutsystems von Compose und die Canvas
-Koordinaten [0, 0]
darstellen, sind die obere linke Ecke und die Achsen x
und y
nach unten positiv, sodass der Wert MaxChartValue
immer kleiner als MinChartValue
ist. Daher lautet die Zusammenführungsrichtlinie min
für die maximale Referenz des Diagrammdatenwerts und max
für die minimale Referenz des Diagrammdatenwerts.
Geben Sie beim Erstellen eines benutzerdefinierten Layout
oder LayoutModifier
benutzerdefinierte Ausrichtungslinien in der Methode MeasureScope.layout
an, für die ein alignmentLines: Map<AlignmentLine, Int>
-Parameter verwendet wird.
@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() ) ) {} } } } } }
Direkte und indirekte übergeordnete Elemente dieser zusammensetzbaren Funktion können die Ausrichtungslinien nutzen. Mit der folgenden zusammensetzbaren Funktion wird ein benutzerdefiniertes Layout erstellt, das als Parameter zwei Text
-Slots und Datenpunkte verwendet und die beiden Texte auf die maximalen und minimalen Diagrammdatenwerte ausrichtet. Die Vorschau dieser zusammensetzbaren
Funktion ist in Abbildung 2 zu sehen.
@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) ) } }
Empfehlungen für dich
- Hinweis: Der Linktext wird angezeigt, wenn JavaScript deaktiviert ist.
- Grafiken in Compose
- Benutzerdefinierte Layouts {:#custom-layouts }
- Intrinsische Messungen in Compose-Layouts