Model układu Utwórz umożliwia tworzenie niestandardowych linii wyrównania za pomocą narzędzia AlignmentLine
, którego mogą używać układy nadrzędne do wyrównywania i pozycjonowania elementów podrzędnych. Na przykład Row
może wyrównać elementy podrzędne za pomocą niestandardowych linii wyrównywania.
Gdy układ podaje wartość określonej AlignmentLine
, elementy nadrzędne układu mogą odczytać tę wartość po przeprowadzeniu pomiaru, używając operatora Placeable.get
w odpowiednim instancji Placeable
.
Na podstawie pozycji AlignmentLine
rodzice mogą zdecydować o położeniu elementów podrzędnych.
Niektóre elementy kompozycyjne w sekcji Utwórz mają już linie wyrównania. Na przykład funkcja kompozycyjna BasicText
ujawnia linie wyrównania FirstBaseline
i LastBaseline
.
W przykładzie poniżej niestandardowy obiekt LayoutModifier
o nazwie firstBaselineToTop
odczytuje wartość FirstBaseline
, aby dodać dopełnienie do elementu Text
, począwszy od pierwszej wartości bazowej.
Rysunek 1. Pokazuje różnicę między dodaniem normalnego dopełnienia elementu a dodaniem dopełnienia do punktu odniesienia elementu tekstowego.
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)) } }
Do odczytywania parametru FirstBaseline
w przykładzie używany jest placeable [FirstBaseline]
na etapie pomiaru.
Utwórz niestandardowe linie wyrównania
Podczas tworzenia niestandardowego elementu Layout
kompozycyjnego lub niestandardowego elementu LayoutModifier
możesz podać niestandardowe linie wyrównania, aby inne nadrzędne elementy kompozycyjne mogły używać ich do wyrównywania i pozycjonowania elementów podrzędnych.
Poniższy przykład przedstawia niestandardowy element kompozycyjny BarChart
z 2 liniami wyrównania: MaxChartValue
i MinChartValue
, dzięki czemu inne funkcje kompozycyjne mogą być zgodne z maksymalną i minimalną wartością danych na wykresie. Dwa elementy tekstowe – Max i Min – zostały wyrównane do środka niestandardowych linii wyrównania.
Rysunek 2. Element kompozycyjny BarChart
z tekstem wyrównanym do maksymalnej i minimalnej wartości danych.
Niestandardowe linie wyrównania są zdefiniowane 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 używane w naszym przykładzie mają typ HorizontalAlignmentLine
, ponieważ służą do wyrównywania elementów podrzędnych w pionie. Zasada scalania jest przekazywana jako parametr w przypadku, gdy wiele układów podaje wartość dla tych linii wyrównania. Jako że współrzędne systemu układu tworzenia tworzenia, a współrzędne Canvas
to [0, 0]
, lewy górny róg i oś x
i y
mają wartości dodatnie, więc wartość MaxChartValue
będzie zawsze mniejsza niż MinChartValue
. Dlatego zasada scalania wynosi min
w przypadku maksymalnej wartości bazowej danych wykresu i max
dla minimalnej wartości bazowej wykresu.
Podczas tworzenia niestandardowego elementu Layout
lub LayoutModifier
określ niestandardowe linie wyrównania w metodzie MeasureScope.layout
, która pobiera 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. Podany niżej element kompozycyjny tworzy układ niestandardowy, który jako parametr przyjmuje jako parametr 2 boksy Text
i punkty danych, a potem wyrównuje te 2 teksty do minimalnych i maksymalnych 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 JavaScript jest wyłączony
- Grafika w obszarze tworzenia wiadomości
- Układy niestandardowe {:#custom-layouts }
- Pomiary wewnętrzne w układach tworzenia wiadomości