Model układu Compose umożliwia używanie elementu AlignmentLine do tworzenia niestandardowych
linii wyrównania, których mogą używać układy nadrzędne do wyrównywania i pozycjonowania elementów
podrzędnych. Na przykład element Row może używać niestandardowych linii wyrównania elementów podrzędnych
do ich wyrównywania.
Gdy układ podaje wartość dla określonego elementu AlignmentLine, układy nadrzędne mogą odczytać tę wartość po pomiarze za pomocą operatora Placeable.get w odpowiednim wystąpieniu elementu Placeable. Na podstawie pozycji elementu AlignmentLine układy nadrzędne mogą następnie określić pozycjonowanie elementów podrzędnych.
Niektóre elementy kompozycyjne w Compose mają już linie wyrównania. Na przykład element kompozycyjny
BasicText udostępnia FirstBaseline i LastBaseline
linie wyrównania.
W poniższym przykładzie niestandardowy element LayoutModifier o nazwie
firstBaselineToTop odczytuje element FirstBaseline, aby dodać do elementu Text
dopełnienie zaczynające się od jego pierwszej linii bazowej.
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)) } }
Aby odczytać element FirstBaseline w przykładzie, placeable [FirstBaseline]
jest używany w fazie pomiaru.
Tworzenie niestandardowych linii wyrównania
Podczas tworzenia niestandardowego elementu kompozycyjnego Layout lub niestandardowego elementu
LayoutModifier możesz podać niestandardowe linie wyrównania, aby inne
nadrzędne elementy kompozycyjne mogły ich używać do wyrównywania i pozycjonowania elementów podrzędnych
odpowiednio.
Poniższy przykład pokazuje niestandardowy element kompozycyjny BarChart, który udostępnia 2 linie wyrównania: MaxChartValue i MinChartValue. Dzięki temu inne elementy kompozycyjne mogą wyrównywać się do maksymalnej i minimalnej wartości danych na wykresie. Dwa elementy tekstowe,
Max i Min, zostały wyrównane do środka niestandardowych linii wyrównania.
BarChart z tekstem wyrównanym do maksymalnej i
minimalnej wartości danych.Niestandardowe linie wyrównania są definiowane jako zmienne najwyższego poziomu w projekcie.
/** * 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) })
Niestandardowe linie wyrównania, które tworzą nasz przykład, są typu
HorizontalAlignmentLine, ponieważ
służą do wyrównywania elementów podrzędnych w pionie. W przypadku, gdy wiele układów podaje wartość dla tych linii wyrównania, jako parametr przekazywana jest zasada scalania. Ponieważ
system układu Compose i współrzędne elementu Canvas
reprezentują wartość [0, 0], lewy górny róg, a osie x i y są
dodatnie w dół, wartość MaxChartValue będzie zawsze mniejsza niż
MinChartValue. Dlatego zasada scalania to min w przypadku linii bazowej maksymalnej wartości danych na wykresie i max w przypadku linii bazowej minimalnej wartości danych na wykresie.
Podczas tworzenia niestandardowego elementu Layout lub LayoutModifier określ niestandardowe linie wyrównania
w metodzie MeasureScope.layout, która przyjmuje parametr
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() ) ) {} } } } } }
Linie wyrównania mogą być używane przez bezpośrednich i pośrednich rodziców tego elementu kompozycyjnego. Poniższy element kompozycyjny tworzy układ niestandardowy, który przyjmuje jako parametr 2 miejsca na element Text i punkty danych, a następnie wyrównuje 2 teksty do maksymalnej i minimalnej wartości danych na wykresie. Podgląd tego elementu kompozycyjnego jest widoczny na rysunku 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) ) } }
Polecane dla Ciebie
- Uwaga: tekst linku jest wyświetlany, gdy język JavaScript jest wyłączony.
- Grafika w Compose
- Układy niestandardowe {:#custom-layouts }
- Wymiary wewnętrzne w układach Compose