El modelo de diseño de Compose te permite usar AlignmentLine para crear líneas de alineación personalizadas que los diseños de nivel superior pueden usar para alinear y posicionar sus elementos secundarios. Por ejemplo, Row puede usar las líneas de alineación personalizadas de sus elementos secundarios para alinearlos.
Cuando un diseño proporciona un valor para un AlignmentLine en particular, los elementos superiores del diseño pueden leer este valor después de la medición, con el operador Placeable.get en la instancia Placeable correspondiente. Según la posición
del AlignmentLine, los padres pueden decidir la posición de los
elementos secundarios.
Algunos elementos de Compose que admiten composición ya incluyen líneas de alineación. Por ejemplo, el elemento componible BasicText expone las líneas de alineación FirstBaseline y LastBaseline.
En el siguiente ejemplo, un LayoutModifier personalizado llamado firstBaselineToTop lee el FirstBaseline para agregar padding al Text a partir de su primera línea de base.

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)) } }
Para leer el FirstBaseline en el ejemplo, se usa placeable [FirstBaseline] en la fase de medición.
Crea líneas de alineación personalizadas
Cuando creas un elemento de componibilidad Layout o un LayoutModifier personalizados, puedes proporcionar líneas de alineación personalizadas para que otros elementos de componibilidad superiores puedan usarlas para alinear y posicionar sus elementos secundarios según corresponda.
En el siguiente ejemplo, se muestra un elemento BarChart que admite composición y muestra dos líneas de alineación, MaxChartValue y MinChartValue, de modo que otros elementos que admitan composición puedan alinearse con el valor de datos máximo y mínimo del gráfico. Dos elementos de texto, Max y Min, se alinearon con el centro de las líneas de alineación personalizadas.

BarChart componible con texto alineado con el valor de datos máximo y mínimoLas líneas de alineación personalizadas se definen como variables de nivel superior en tu proyecto.
/** * 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) })
Las líneas de alineación personalizadas que se utilizan en la creación de nuestro ejemplo son del tipo HorizontalAlignmentLine, ya que su función es alinear verticalmente los elementos secundarios. Se pasa una política de combinación como parámetro en caso de que varios diseños proporcionen un valor para estas líneas de alineación. Mientras las coordenadas del sistema de diseño de Compose y las coordenadas de Canvas representen [0, 0], la esquina superior izquierda y los ejes x y y serán positivos hacia abajo, para que el valor MaxChartValue siempre sea menor que MinChartValue. Por lo tanto, la política de combinación es min para el modelo de referencia del valor máximo de los datos del gráfico y max para el modelo de referencia del valor mínimo de los datos del gráfico.
Cuando crees un Layout o LayoutModifier personalizado, especifica líneas de alineación personalizadas en el método MeasureScope.layout, que toma un parámetro 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() ) ) {} } } } } }
Los elementos superiores directos e indirectos de este elemento que admite composición pueden consumir las líneas de alineación. El siguiente elemento que admite composición crea un diseño personalizado que toma como parámetro dos ranuras y datos Text, y alinea los dos textos con los valores de datos de los gráficos máximo y mínimo. La vista previa de este elemento que admite composición es la que se muestra en la Figura 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) ) } }
Recomendaciones para ti
- Nota: El texto del vínculo se muestra cuando JavaScript está desactivado
- Gráficos en Compose
- Diseños personalizados {:#custom-layouts }
- Mediciones intrínsecas en los diseños de Compose