Model układu Compose umożliwia używanie AlignmentLine do tworzenia niestandardowych linii wyrównania, które mogą być używane przez układy nadrzędne do wyrównywania i pozycjonowania elementów podrzędnych. Na przykład Row może używać niestandardowych linii wyrównania elementów podrzędnych, aby je wyrównać.
Gdy układ podaje wartość dla określonego elementu AlignmentLine, elementy nadrzędne układu mogą odczytać tę wartość po pomiarze, używając operatora Placeable.get w odpowiedniej instancji Placeable. Na podstawie pozycji elementu AlignmentLine rodzice mogą zdecydować o pozycjonowaniu elementów podrzędnych.
Niektóre elementy kompozycyjne w Compose mają już linie wyrównania. Na przykład funkcja kompozycyjna BasicText udostępnia linie wyrównania FirstBaseline i LastBaseline.
W poniższym przykładzie niestandardowy LayoutModifier o nazwie firstBaselineToTop odczytuje FirstBaseline, aby dodać dopełnienie do Text, zaczynając od 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ć FirstBaseline w przykładzie, w fazie pomiaru używany jest placeable [FirstBaseline].
Tworzenie niestandardowych linii ułatwiających wyrównanie
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 odpowiedniego wyrównywania i pozycjonowania elementów podrzędnych.
W tym przykładzie pokazano niestandardowy element kompozycyjny BarChart, który udostępnia 2 linie wyrównania, MaxChartValue i MinChartValue, dzięki czemu 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 funkcja kompozycyjna 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 posłużą do utworzenia naszego przykładu, są typu HorizontalAlignmentLine, ponieważ służą do wyrównywania elementów podrzędnych w pionie. Zasada scalania jest przekazywana jako parametr, jeśli wiele układów zawiera wartość dla tych linii wyrównania. Współrzędne systemu układu Compose i współrzędne Canvas reprezentują [0, 0], lewy górny róg oraz osie x i y są dodatnie w dół, więc wartość MaxChartValue będzie zawsze mniejsza niż MinChartValue. Dlatego zasada scalania to min dla punktu odniesienia maksymalnej wartości danych na wykresie i max dla punktu odniesienia 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() ) ) {} } } } } }
Bezpośrednie i pośrednie elementy nadrzędne tego elementu kompozycyjnego mogą wykorzystywać linie wyrównania. Poniższa funkcja kompozycyjna tworzy układ niestandardowy, który przyjmuje jako parametr 2 boksy Text i punkty danych oraz wyrównuje 2 teksty do maksymalnych i minimalnych 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 }
- Pomiary wewnętrzne w układach Compose