Una de las reglas de Compose es que solo debes medir tus elementos secundarios una vez. Si lo haces dos veces, se genera una excepción de tiempo de ejecución. Sin embargo, hay momentos en los que necesitas información sobre tus elementos secundarios antes de medirlos.
Los elementos intrínsecos te permiten realizar consultas a los elementos secundarios antes de que se midan realmente.
Para un elemento componible, puedes solicitar su IntrinsicSize.Min
o IntrinsicSize.Max
:
Modifier.width(IntrinsicSize.Min)
: ¿Cuál es el ancho mínimo que necesitas para mostrar tu contenido de forma correcta?Modifier.width(IntrinsicSize.Max)
: ¿Cuál es el ancho máximo que necesitas para mostrar tu contenido de forma correcta?Modifier.height(IntrinsicSize.Min)
: ¿Cuál es la altura mínima que necesitas para mostrar tu contenido de forma correcta?Modifier.height(IntrinsicSize.Max)
: ¿Cuál es la altura máxima que necesitas para mostrar tu contenido de forma correcta?
Por ejemplo, si solicitas la minIntrinsicHeight
de un Text
con restricciones de width
infinitas en un diseño personalizado, se mostrará la height
del Text
con el texto dibujado en una sola línea.
Funciones intrínsecas en acción
Imagina que queremos crear un elemento componible que muestre dos textos en la pantalla separados por un divisor como este:
¿Cómo podemos hacer esto? Podemos tener un objeto Row
con dos Text
que se expandan tanto como sea posible y un Divider
en el medio. Queremos que el Divider
sea tan alto como el Text
más alto y delgado (width = 1.dp
).
@Composable fun TwoTexts(modifier: Modifier = Modifier, text1: String, text2: String) { Row(modifier = modifier) { Text( modifier = Modifier .weight(1f) .padding(start = 4.dp) .wrapContentWidth(Alignment.Start), text = text1 ) VerticalDivider( color = Color.Black, modifier = Modifier.fillMaxHeight().width(1.dp) ) Text( modifier = Modifier .weight(1f) .padding(end = 4.dp) .wrapContentWidth(Alignment.End), text = text2 ) } }
En la vista previa, vemos que el Divider
se expande a toda la pantalla, pero eso no es lo que deseamos:
Esto ocurre porque Row
mide cada elemento secundario de forma individual, y la altura de Text
no se puede usar para restringir Divider
. Queremos que el Divider
ocupe el espacio disponible con una altura determinada. Para eso, podemos usar el modificador height(IntrinsicSize.Min)
.
height(IntrinsicSize.Min)
ajusta su tamaño a los elementos secundarios para que sean tan altos como su altura mínima intrínseca. Como es recurrente, realizará consultas a Row
y sus elementos secundarios minIntrinsicHeight
.
Cuando lo apliquemos a nuestro código, funcionará según lo esperado:
@Composable fun TwoTexts(modifier: Modifier = Modifier, text1: String, text2: String) { Row(modifier = modifier.height(IntrinsicSize.Min)) { Text( modifier = Modifier .weight(1f) .padding(start = 4.dp) .wrapContentWidth(Alignment.Start), text = text1 ) VerticalDivider( color = Color.Black, modifier = Modifier.fillMaxHeight().width(1.dp) ) Text( modifier = Modifier .weight(1f) .padding(end = 4.dp) .wrapContentWidth(Alignment.End), text = text2 ) } } // @Preview @Composable fun TwoTextsPreview() { MaterialTheme { Surface { TwoTexts(text1 = "Hi", text2 = "there") } } }
Con vista previa:
El elemento componible minIntrinsicHeight
de la Row
será la minIntrinsicHeight
máxima de sus elementos secundarios. El elemento minIntrinsicHeight
de Divider
es 0, ya que no ocupa espacio si no se le aplican restricciones. El minIntrinsicHeight
de Text
será el del texto según un width
específico. Por lo tanto, la restricción height
del elemento Row
será la minIntrinsicHeight
máxima de los Text
. Luego, Divider
expandirá su height
a la restricción height
proporcionada por Row
.
Funciones intrínsecas en tus diseños personalizados
Cuando se crea un modificador Layout
o layout
personalizado, las mediciones intrínsecas se calculan automáticamente en función de aproximaciones. Por lo tanto, es posible que los cálculos no sean correctos para todos los diseños. Estas APIs ofrecen opciones para anular estos valores predeterminados.
Para especificar las mediciones intrínsecas de tu Layout
personalizado, anula minIntrinsicWidth
, minIntrinsicHeight
, maxIntrinsicWidth
y maxIntrinsicHeight
de MeasurePolicy
cuando la creas.
@Composable fun MyCustomComposable( modifier: Modifier = Modifier, content: @Composable () -> Unit ) { Layout( content = content, modifier = modifier, measurePolicy = object : MeasurePolicy { override fun MeasureScope.measure( measurables: List<Measurable>, constraints: Constraints ): MeasureResult { // Measure and layout here // ... } override fun IntrinsicMeasureScope.minIntrinsicWidth( measurables: List<IntrinsicMeasurable>, height: Int ): Int { // Logic here // ... } // Other intrinsics related methods have a default value, // you can override only the methods that you need. } ) }
Cuando crees el modificador layout
personalizado, anula los métodos relacionados en la interfaz LayoutModifier
.
fun Modifier.myCustomModifier(/* ... */) = this then object : LayoutModifier { override fun MeasureScope.measure( measurable: Measurable, constraints: Constraints ): MeasureResult { // Measure and layout here // ... } override fun IntrinsicMeasureScope.minIntrinsicWidth( measurable: IntrinsicMeasurable, height: Int ): Int { // Logic here // ... } // Other intrinsics related methods have a default value, // you can override only the methods that you need. }
No hay recomendaciones en este momento.
Intenta acceder a tu Cuenta de Google.