WindowInsets es la API estándar de Jetpack Compose para controlar las áreas de la pantalla que la IU del sistema oculta de forma parcial o total. Estas áreas incluyen la barra de estado, la barra de navegación y el teclado en pantalla. Como alternativa, puedes pasar WindowInsetsRulers predefinidos, como SafeDrawing, a Modifier.fitInside o Modifier.fitOutside para alinear el contenido con las barras del sistema y el corte de pantalla, o bien crear WindowInsetsRulers personalizados.
Ventajas de WindowInsetsRulers
- Evita la complejidad del consumo: Opera durante la fase de posicionamiento del diseño. Esto significa que omite por completo la cadena de consumo de inserciones y siempre puede proporcionar las posiciones correctas y absolutas de las barras del sistema y los cortes de pantalla, independientemente de lo que hayan hecho los diseños de nivel superior. Usar los métodos
Modifier.fitInsideoModifier.fitOutsidees útil para solucionar problemas cuando los elementos componibles principales consumen inserciones de forma incorrecta. - Evita fácilmente las barras del sistema: Ayuda a que el contenido de tu app evite las barras del sistema y el corte de pantalla, y puede ser más sencillo que usar
WindowInsetsdirectamente. - Altamente personalizable: Los desarrolladores pueden alinear el contenido con reglas personalizadas y tener un control preciso sobre sus diseños con diseños personalizados.
Desventajas de WindowInsetsRulers
- No se puede usar para la medición: Debido a que opera durante la fase de ubicación, la información posicional que proporciona no está disponible durante la fase de medición anterior.
Alinea tu contenido con los métodos de Modifier
Modifier.fitInside permite que las apps alineen el contenido con las barras del sistema y los cortes de pantalla. Se puede usar en lugar de WindowInsets.
Modifier.fitOutside suele ser el inverso de Modifier.fitInside.
Por ejemplo, para verificar que el contenido de la app evite las barras del sistema y el corte de pantalla, puedes usar fitInside(WindowInsetsRulers.safeDrawing.current).
@Composable fun FitInsideDemo(modifier: Modifier) { Box( modifier = modifier .fillMaxSize() // Or DisplayCutout, Ime, NavigationBars, StatusBar, etc... .fitInside(WindowInsetsRulers.SafeDrawing.current) ) }
En la siguiente tabla, se muestra cómo se vería el contenido de tu app con reglas predefinidas con Modifier.fitInside o Modifier.fitOutside.
| Tipo de regla predefinido | ||
|---|---|---|
![]() |
![]() |
|
![]() |
N/A |
|
![]() |
![]() |
|
![]() |
N/A (usa |
|
![]() |
![]() |
El uso de Modifier.fitInside y Modifier.fitOutside requiere que los elementos componibles estén restringidos. Esto significa que debes definir modificadores como Modifier.size o Modifier.fillMaxSize.
Algunas reglas, como Modifier.fitOutside en SafeDrawing y SystemBars, devuelven
varias reglas. En este caso, Android coloca el elemento que admite composición con una regla desde la izquierda, la parte superior, la derecha y la parte inferior.
Evita el IME con Modifier.fitInside
Para controlar los elementos inferiores con un IME con Modifier.fitInside, pasa un RectRuler que tome el valor más interno de NavigationBar y Ime.
@Composable fun FitInsideWithImeDemo(modifier: Modifier) { Box( modifier = modifier .fillMaxSize() .fitInside( RectRulers.innermostOf( WindowInsetsRulers.NavigationBars.current, WindowInsetsRulers.Ime.current ) ) ) { TextField( value = "Demo IME Insets", onValueChange = {}, modifier = modifier.align(Alignment.BottomStart).fillMaxWidth() ) } }
Evita la barra de estado y la barra de subtítulos con Modifier.fitInside
De manera similar, para verificar que los elementos superiores eviten la barra de estado y la barra de subtítulos junto con Modifier.fitInside, pasa un RectRuler que tome el valor más interno de StatusBars y CaptionBar.
@Composable fun FitInsideWithStatusAndCaptionBarDemo(modifier: Modifier) { Box( modifier = modifier .fillMaxSize() .fitInside( RectRulers.innermostOf( WindowInsetsRulers.StatusBars.current, WindowInsetsRulers.CaptionBar.current ) ) ) }
Crea WindowInsetsRulers personalizadas
Puedes alinear el contenido con reglas personalizadas. Por ejemplo, considera el caso de uso en el que un elemento componible superior controla de forma incorrecta las inserciones, lo que causa problemas de padding en un elemento secundario descendente. Si bien este problema se puede resolver de otras maneras, como con Modifier.fitInside, también puedes crear una regla personalizada para alinear con precisión el elemento componible secundario sin tener que solucionar el problema en el elemento superior, como se muestra en el siguiente ejemplo y video:
@Composable fun WindowInsetsRulersDemo(modifier: Modifier) { Box( contentAlignment = BottomCenter, modifier = modifier .fillMaxSize() // The mistake that causes issues downstream, as .padding doesn't consume insets. // While it's correct to instead use .windowInsetsPadding(WindowInsets.navigationBars), // assume it's difficult to identify this issue to see how WindowInsetsRulers can help. .padding(WindowInsets.navigationBars.asPaddingValues()) ) { TextField( value = "Demo IME Insets", onValueChange = {}, modifier = modifier // Use alignToSafeDrawing() instead of .imePadding() to precisely place this child // Composable without having to fix the parent upstream. .alignToSafeDrawing() // .imePadding() // .fillMaxWidth() ) } } fun Modifier.alignToSafeDrawing(): Modifier { return layout { measurable, constraints -> if (constraints.hasBoundedWidth && constraints.hasBoundedHeight) { val placeable = measurable.measure(constraints) val width = placeable.width val height = placeable.height layout(width, height) { val bottom = WindowInsetsRulers.SafeDrawing.current.bottom .current(0f).roundToInt() - height val right = WindowInsetsRulers.SafeDrawing.current.right .current(0f).roundToInt() val left = WindowInsetsRulers.SafeDrawing.current.left .current(0f).roundToInt() measurable.measure(Constraints.fixed(right - left, height)) .place(left, bottom) } } else { val placeable = measurable.measure(constraints) layout(placeable.width, placeable.height) { placeable.place(0, 0) } } } }
En el siguiente video, se muestra un ejemplo de consumo problemático de inserciones de IME causado por un elemento superior en la imagen de la izquierda y el uso de reglas personalizadas para solucionar el problema de la derecha. Se muestra un padding adicional debajo del elemento de componibilidad TextField, ya que el elemento superior no consumió el padding de la barra de navegación. El elemento secundario se coloca en la ubicación correcta en la imagen de la derecha con una regla personalizada, como se ve en la muestra de código anterior.
Verifica que los elementos superiores estén restringidos
Para usar WindowInsetsRulers de forma segura, asegúrate de que el elemento superior proporcione restricciones válidas. Los elementos superiores deben tener un tamaño definido y no pueden depender del tamaño de un elemento secundario que use WindowInsetsRulers. Usa fillMaxSize o algún otro modificador de tamaño en los elementos componibles superiores.
Del mismo modo, colocar un elemento componible que use WindowInsetsRulers dentro de un contenedor de desplazamiento, como verticalScroll, puede causar un comportamiento inesperado, ya que el contenedor de desplazamiento proporciona restricciones de altura ilimitadas, que son incompatibles con la lógica de la regla.







