Mit dem Compose-Layoutmodell können Sie AlignmentLine verwenden, um benutzerdefinierte Ausrichtungslinien zu erstellen, die von übergeordneten Layouts verwendet werden können, um ihre untergeordneten Elemente auszurichten und zu positionieren. Beispielsweise kann Row die benutzerdefinierten Ausrichtungslinien seiner untergeordneten Elemente verwenden, um sie auszurichten.
Wenn ein Layout einen Wert für ein bestimmtes AlignmentLine bereitstellt, können die übergeordneten Elemente des Layouts diesen Wert nach der Messung mit dem Operator Placeable.get für die entsprechende Placeable-Instanz lesen. Anhand der Position des AlignmentLine können die Eltern dann die Positionierung der Kinder festlegen.
Einige Composeables in Compose haben bereits Ausrichtungslinien. Beispielsweise stellt die komponierbare Funktion BasicText die Ausrichtungslinien FirstBaseline und LastBaseline bereit.
Im folgenden Beispiel liest ein benutzerdefiniertes LayoutModifier namens firstBaselineToTop den FirstBaseline, um der Text ab der ersten Referenzlinie einen Abstand hinzuzufügen.
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)) } }
Um die FirstBaseline im Beispiel zu lesen, wird in der Messphase placeable [FirstBaseline] verwendet.
Benutzerdefinierte Ausrichtungslinien erstellen
Wenn Sie ein benutzerdefiniertes Layout- oder LayoutModifier-Composable erstellen, können Sie benutzerdefinierte Ausrichtungslinien angeben, damit andere übergeordnete Composables sie verwenden können, um ihre untergeordneten Elemente entsprechend auszurichten und zu positionieren.
Im folgenden Beispiel wird eine benutzerdefinierte BarChart-komponierbare Funktion gezeigt, die zwei Ausrichtungslinien (MaxChartValue und MinChartValue) verfügbar macht, damit andere komponierbare Funktionen am maximalen und minimalen Datenwert des Diagramms ausgerichtet werden können. Zwei Textelemente, Max und Min, wurden an der Mitte der benutzerdefinierten Ausrichtungslinien ausgerichtet.
BarChart-Composable mit Text, der am maximalen und minimalen Datenwert ausgerichtet ist.Benutzerdefinierte Ausrichtungslinien werden als Variablen auf oberster Ebene in Ihrem Projekt 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 zum Erstellen unseres Beispiels sind vom Typ HorizontalAlignmentLine, da sie zum vertikalen Ausrichten von untergeordneten Elementen verwendet werden. Eine Zusammenführungsrichtlinie wird als Parameter übergeben, falls mehrere Layouts einen Wert für diese Ausrichtungslinien bereitstellen. Da die Koordinaten des Compose-Layoutsystems und die Canvas-Koordinaten [0, 0] darstellen, sind die obere linke Ecke und die x- und y-Achse nach unten positiv, sodass der MaxChartValue-Wert immer kleiner als MinChartValue ist. Daher ist die Zusammenführungsrichtlinie für die Referenzlinie des maximalen Diagrammdatenwerts min und für die Referenzlinie des minimalen Diagrammdatenwerts max.
Wenn Sie eine benutzerdefinierte Layout oder LayoutModifier erstellen, geben Sie benutzerdefinierte Ausrichtungslinien in der Methode MeasureScope.layout an, die einen alignmentLines: Map<AlignmentLine, Int>-Parameter akzeptiert.
@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. Die folgende zusammensetzbare Funktion erstellt ein benutzerdefiniertes Layout, das zwei Text-Slots und Datenpunkte als Parameter verwendet und die beiden Texte an den maximalen und minimalen Diagrammdatenwerten 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 Sie
- Hinweis: Der Linktext wird angezeigt, wenn JavaScript deaktiviert ist.
- Grafiken in Compose
- Benutzerdefinierte Layouts {:#custom-layouts }
- Intrinsische Messungen in Compose-Layouts