WindowInsets es la API estándar en Jetpack Compose para controlar las áreas de la pantalla que están parcial o completamente ocultas por la IU del sistema. 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 tu 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 absolutas correctas de las barras del sistema y los cortes de pantalla, independientemente de lo que hayan hecho los diseños superiores. El uso de los métodos
Modifier.fitInsideoModifier.fitOutsidees útil para solucionar problemas cuando los elementos componibles superiores 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 posicionamiento, 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 lo contrario 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 predefinida | ||
|---|---|---|
![]() |
![]() |
|
![]() |
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, muestran varias reglas. En este caso, Android coloca el elemento componible con una regla de izquierda, arriba, derecha y abajo.
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
Del mismo modo, 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 personalizados
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 relleno en un elemento secundario inferior. Si bien este problema se puede resolver de otras maneras, incluso 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 de inserciones de IME problemático causado por un elemento superior en la imagen de la izquierda y el uso de reglas personalizadas para solucionar el problema en la derecha. Se muestra un relleno adicional debajo del elemento componible TextField, ya que el elemento superior no consumió el relleno 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 el ejemplo 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 cualquier 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 no delimitadas, que son incompatibles con la lógica de la regla.







