La plataforma de Android se encarga de dibujar la IU del sistema, como el la barra de estado y la barra de navegación. Se muestra la IU del sistema independientemente de cuál la app que el usuario utiliza.
WindowInsets
proporciona información sobre el sistema
IU para garantizar que tu app se dibuje en el área correcta y que no esté oscurecida
por la IU del sistema.
![Ir de borde a borde para dibujar detrás de las barras del sistema](https://developer.android.com/static/develop/ui/compose/images/layouts/insets/e2e-intro.gif?authuser=9&hl=es)
En Android 14 (nivel de API 34) y versiones anteriores, la IU de tu app no se dibuja debajo las barras del sistema y los cortes de pantalla de forma predeterminada.
En Android 15 (nivel de API 35) y versiones posteriores, tu app se dibuja debajo del sistema barras y cortes de pantalla cuando la app se segmente al SDK 35. Esto da como resultado una una experiencia del usuario fluida y que permita que tu app aproveche al máximo el espacio de ventana disponible.
La visualización de contenido detrás de la IU del sistema se denomina ir de borde a borde. En este aprenderás sobre los diferentes tipos de inserciones, cómo ir de borde a borde y cómo usar las APIs de inserción para animar tu IU y garantizar que el contenido de tu app no se obstruyan los elementos de la IU del sistema.
Aspectos básicos de la inserción
Cuando una app va de borde a borde, debes asegurarte de que el contenido y las interacciones no quedan ocultas por la IU del sistema. Por ejemplo, si un botón está detrás de la barra de navegación, es posible que el usuario no pueda hacer clic en ella.
Se especifican el tamaño de la IU del sistema y la información sobre dónde se coloca a través de las inserciones.
Cada parte de la IU del sistema tiene un tipo de inserción correspondiente que describe lo siguiente: su tamaño y dónde está ubicado. Por ejemplo, las inserciones de la barra de estado proporcionan el tamaño y posición de la barra de estado, mientras que las inserciones de la barra de navegación tamaño y posición de la barra de navegación. Cada tipo de inserción consta de cuatro dimensiones de píxeles: superior, izquierdo, derecho e inferior. Estas dimensiones especifican la IU del sistema se extiende desde los lados correspondientes de la ventana de la app. Para evitar que se superpone con ese tipo de IU del sistema, por lo tanto, la IU de la app debe insertarse importe.
Estos tipos de inserciones integrados de Android están disponibles a través de WindowInsets
:
Inserciones que describen las barras de estado Estas son las barras superiores de la IU del sistema que contienen íconos de notificaciones y otros indicadores. |
|
La barra de estado se inserta cuando están visibles. Si las barras de estado están ocultas (debido al modo de pantalla completa envolvente), las inserciones de la barra de estado principal estarán vacías, pero no lo estarán. |
|
Las inserciones que describen las barras de navegación Son las barras de la IU del sistema en el lado izquierdo, derecho o inferior del dispositivo, que describen la barra de tareas o los íconos de navegación. Estas pueden cambiar en el tiempo de ejecución en función del método de navegación preferido del usuario y la interacción con la barra de tareas. |
|
Las inserciones de la barra de navegación para cuando estén visibles Si las barras de navegación están ocultas (debido al modo de pantalla completa envolvente), las inserciones de la barra de navegación principal estarán vacías, pero no lo estarán. |
|
Es la inserción que describe la decoración de la ventana de la IU del sistema en una ventana de formato libre, como la barra de título superior. |
|
La barra de subtítulos se inserta para cuando estén visibles. Si las barras de subtítulos están ocultas, las inserciones principales de la barra de subtítulos estarán vacías, pero no lo estarán. |
|
Es la unión de las inserciones de la barra del sistema, que incluyen las barras de estado, de navegación y de subtítulos. |
|
La barra del sistema se inserta para cuando están visibles. Si las barras del sistema están ocultas (debido al modo de pantalla completa envolvente), las inserciones de la barra principal del sistema estarán vacías, pero no estarán vacías. |
|
Inserciones que describen la cantidad de espacio en la parte inferior que ocupa el teclado en pantalla. |
|
Son las inserciones que describen la cantidad de espacio que ocupaba el teclado en pantalla antes de la animación del teclado actual. |
|
Son las inserciones que describen la cantidad de espacio que ocupará el teclado en pantalla después de la animación del teclado actual. |
|
Un tipo de inserciones que describen información más detallada sobre la IU de navegación, que proporciona la cantidad de espacio en la que se presionan los elementos no serán manejados por el sistema, no por la app. En el caso de las barras de navegación transparentes con navegación por gestos, algunos elementos de la app se pueden presionar a través de la IU de navegación del sistema. |
|
Las inserciones de elementos que se pueden presionar para cuando son visibles Si los elementos que se pueden presionar están ocultos (debido al modo de pantalla completa envolvente), las inserciones de elementos principales que se pueden presionar estarán vacías, pero estas inserciones no estarán vacías. |
|
Las inserciones que representan la cantidad de inserciones en las que el sistema interceptará gestos para la navegación Las apps pueden especificar manualmente el control de una cantidad limitada de estos gestos a través de |
|
Un subconjunto de los gestos del sistema que el sistema siempre controlará y que no se pueden inhabilitar a través de |
|
Las inserciones que representan la cantidad de espaciado necesario para evitar superponerse con un corte de pantalla (muesca o estenopeica). |
|
Se muestran las inserciones que representan las áreas curvas de una cascada. Una pantalla de cascada tiene áreas curvas a lo largo de los bordes de la pantalla donde la pantalla comienza a ajustarse a los lados del dispositivo. |
Estos tipos se resumen en tres tipos de contenido “seguros” los tipos de inserción que garantizan que el contenido no sea oscurecido:
Se consideran "seguros" los tipos de inserción protegen el contenido de diferentes maneras, según el las inserciones subyacentes de la plataforma:
- Usa
WindowInsets.safeDrawing
para proteger el contenido que no se debe dibujar. debajo de cualquier IU del sistema. Este es el uso más común de las inserciones: para evitar dibujar contenido que está oscurecido por la IU del sistema (ya sea de forma parcial o completamente). - Usa
WindowInsets.safeGestures
para proteger el contenido con gestos. Esta Evita que los gestos del sistema entren en conflicto con los de la app (como los de la parte inferior) hojas de cálculo, carruseles o juegos). - Usa
WindowInsets.safeContent
como una combinación deWindowInsets.safeDrawing
yWindowInsets.safeGestures
para garantizar contenido no tiene superposición visual ni de gestos.
Configuración de inserciones
Para permitir que tu app controle por completo dónde dibuja contenido, sigue estos pasos de configuración pasos. Sin estos pasos, tu app podría dibujar colores negros o sólidos detrás de la IU del sistema o no animarlo de forma síncrona con el teclado en pantalla.
- Orienta la app al SDK 35 o versiones posteriores para aplicar de manera forzosa el borde a borde en Android 15 y versiones posteriores. Tu app detrás de la IU del sistema. Puedes ajustar la IU de tu app controlando inserciones.
- De manera opcional, llama a
enableEdgeToEdge()
enActivity.onCreate()
, que permite que tu app sea de borde a borde en versiones anteriores Versiones de Android Configura
android:windowSoftInputMode="adjustResize"
en los camposAndroidManifest.xml
entrada. Este parámetro de configuración permite que tu app reciba el tamaño del IME de software como inserciones, que puedes usar para rellenar y distribuir el contenido correctamente cuando el IME aparezca y desaparezca en tu app.<!-- in your AndroidManifest.xml file: --> <activity android:name=".ui.MainActivity" android:label="@string/app_name" android:windowSoftInputMode="adjustResize" android:theme="@style/Theme.MyApplication" android:exported="true">
APIs de Compose
Una vez que tu actividad haya tomado el control del control de todas las inserciones, puedes usar Compose. para garantizar que el contenido no esté oscurecido y que los elementos interactivos no se superponen con la IU del sistema. Estas APIs también sincronizan el diseño de tu app con cambios en la inserción.
Por ejemplo, este es el método más básico para aplicar las inserciones al contenido. de toda la app:
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) enableEdgeToEdge() setContent { Box(Modifier.safeDrawingPadding()) { // the rest of the app } } }
Este fragmento aplica las inserciones de ventana safeDrawing
como padding alrededor del
todo el contenido de la app. Si bien esto garantiza que los elementos interactivos no
se superponen con la IU del sistema, también
significa que ninguna app se dibujará detrás
la IU del sistema para lograr un efecto de borde a borde. Para aprovechar al máximo la totalidad
ventana, debes ajustar dónde se aplican las inserciones en cada pantalla
o componente por componente.
Todos estos tipos de inserción se animan automáticamente con animaciones IME y adaptarlos al nivel de API 21. Por extensión, todos los diseños que usan estas inserciones también se anima automáticamente a medida que cambian los valores de inserción.
Hay dos formas principales de usar estos tipos de inserción para ajustar tu elemento componible diseños: modificadores de padding y modificadores de tamaño de inserción.
Modificadores de padding
Modifier.windowInsetsPadding(windowInsets: WindowInsets)
aplica la
las inserciones de ventana dadas como relleno, que actúan como lo haría Modifier.padding
.
Por ejemplo, Modifier.windowInsetsPadding(WindowInsets.safeDrawing)
aplica
las inserciones de dibujo seguras como relleno en los 4 lados.
También hay varios métodos de utilidad integrados para los tipos de inserción más comunes.
Modifier.safeDrawingPadding()
es uno de esos métodos, equivalente a
Modifier.windowInsetsPadding(WindowInsets.safeDrawing)
Hay ejemplos similares
para los otros tipos de inserción.
Modificadores de tamaño de inserción
Los siguientes modificadores aplican una cantidad de inserciones de ventana estableciendo el tamaño de que el componente sea el tamaño de las inserciones:
Aplica el lado inicial de windowInsets como el ancho (como |
|
Aplica el extremo del elemento windowInsets como el ancho (como |
|
Aplica el lado superior de windowInsets como la altura (como |
|
|
Aplica el lado inferior de windowInsets como la altura (como |
Estos modificadores son especialmente útiles para ajustar el tamaño de un Spacer
que ocupa la
espacio de inserciones:
LazyColumn( Modifier.imePadding() ) { // Other content item { Spacer( Modifier.windowInsetsBottomHeight( WindowInsets.systemBars ) ) } }
Inserción de consumo
Los modificadores de padding de inserción (windowInsetsPadding
y asistentes como
safeDrawingPadding
) consumen automáticamente la parte de las inserciones que
aplicado como padding. Cuando profundizas en el árbol de composición, la inserción anidada
los modificadores de relleno y los modificadores de tamaño de inserción saben que alguna parte de la
los modificadores de padding externos ya consumieron las inserciones, y evita
usando la misma parte de las inserciones más de una vez, lo que daría como resultado demasiado
mucho espacio extra.
Los modificadores de tamaño de inserción también evitan usar la misma parte de las inserciones más de una vez si las inserciones ya se consumieron. Sin embargo, dado que están cambiando directamente, no consumen las inserciones por sí mismas.
Como resultado, los modificadores de padding de anidación cambian automáticamente la cantidad de padding aplicado a cada elemento componible.
En el mismo ejemplo de LazyColumn
que antes, se muestra LazyColumn
con el modificador imePadding
. Dentro de LazyColumn
, el último elemento se
dimensionado para ser la altura de la parte inferior de las barras del sistema:
LazyColumn( Modifier.imePadding() ) { // Other content item { Spacer( Modifier.windowInsetsBottomHeight( WindowInsets.systemBars ) ) } }
Cuando se cierra el IME, el modificador imePadding()
no aplica padding, ya que
el IME no tiene altura. Como el modificador imePadding()
no aplica padding,
no se consumen inserciones, y la altura de Spacer
será el tamaño de
la parte inferior de las barras del sistema.
Cuando se abre el IME, las inserciones se animan para coincidir con el tamaño del IME, y
El modificador imePadding()
comienza a aplicar padding inferior para cambiar el tamaño
LazyColumn
cuando se abre el IME. Cuando se comienza a aplicar el modificador imePadding()
con padding inferior, también comienza a consumir esa cantidad de inserciones. Por lo tanto, el
la altura de Spacer
comienza a disminuir, como parte del espaciado del sistema
el modificador imePadding()
ya aplicó las barras. Una vez que
El modificador imePadding()
aplica una cantidad de padding inferior más grande
que las barras del sistema, la altura de Spacer
es cero.
Cuando se cierra el IME, los cambios ocurren a la inversa: Spacer
comienza a
expandir desde una altura de cero cuando la imePadding()
se aplique menos que la
en la parte inferior de las barras del sistema, hasta que, finalmente, Spacer
coincida con la altura de
la parte inferior de las barras del sistema una vez que el IME esté completamente animado.
TextField
Este comportamiento se logra a través de la comunicación entre todos
windowInsetsPadding
y se pueden ver influenciados en algunos otros
maneras.
Modifier.consumeWindowInsets(insets: WindowInsets)
también consume inserciones
de la misma manera que Modifier.windowInsetsPadding
, pero no se aplica
las inserciones consumidas como relleno. Esto resulta útil en combinación con la inserción
modificadores de tamaño, para indicar a los hermanos que tiene una cierta cantidad de inserciones
ya se consumió:
Column(Modifier.verticalScroll(rememberScrollState())) { Spacer(Modifier.windowInsetsTopHeight(WindowInsets.systemBars)) Column( Modifier.consumeWindowInsets( WindowInsets.systemBars.only(WindowInsetsSides.Vertical) ) ) { // content Spacer(Modifier.windowInsetsBottomHeight(WindowInsets.ime)) } Spacer(Modifier.windowInsetsBottomHeight(WindowInsets.systemBars)) }
Modifier.consumeWindowInsets(paddingValues: PaddingValues)
se comporta de forma muy
de manera similar a la versión con un argumento WindowInsets
, pero toma un
PaddingValues
arbitrario para consumir. Esto es útil para informar
cuando el relleno o el espaciado lo proporciona algún otro mecanismo
modificadores de padding de inserción, como un Modifier.padding
común o una altura fija
separadores:
@OptIn(ExperimentalLayoutApi::class) Column(Modifier.padding(16.dp).consumeWindowInsets(PaddingValues(16.dp))) { // content Spacer(Modifier.windowInsetsBottomHeight(WindowInsets.ime)) }
En los casos en que las inserciones de ventana sin procesar se necesiten sin consumo, usa el
WindowInsets
directamente o usa WindowInsets.asPaddingValues()
para
Muestra un PaddingValues
de las inserciones que no se ven afectadas por el consumo.
Sin embargo, debido a las advertencias que se indican a continuación, es preferible usar el relleno de las inserciones de ventana.
y modificadores de tamaño de las inserciones de ventana siempre que sea posible.
Fases de inserciones y Jetpack Compose
Compose usa las APIs principales subyacentes de AndroidX para actualizar y animar las inserciones. que usan las APIs de la plataforma subyacente que administran las inserciones. Debido a esa plataforma, comportamiento, las inserciones tienen una relación especial con las fases de Jetpack Compose
El valor de las inserciones se actualiza después de la fase de composición, pero antes de la en la fase de diseño. Esto significa que leer el valor de las inserciones en la composición generalmente usa un valor de las inserciones que es un fotograma tarde. El sistema integrado los modificadores descritos en esta página están diseñados para retrasar el uso de los valores de la inserciones hasta la fase de diseño, lo que garantiza que los valores de inserción se usen en en el mismo marco a medida que se actualizan.
Animaciones del IME del teclado con WindowInsets
Puedes aplicar Modifier.imeNestedScroll()
a un contenedor de desplazamiento para abrir y
Cerrará el IME automáticamente cuando te desplaces a la parte inferior del contenedor.
class WindowInsetsExampleActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) WindowCompat.setDecorFitsSystemWindows(window, false) setContent { MaterialTheme { MyScreen() } } } } @OptIn(ExperimentalLayoutApi::class) @Composable fun MyScreen() { Box { LazyColumn( modifier = Modifier .fillMaxSize() // fill the entire window .imePadding() // padding for the bottom for the IME .imeNestedScroll(), // scroll IME at the bottom content = { } ) FloatingActionButton( modifier = Modifier .align(Alignment.BottomEnd) .padding(16.dp) // normal 16dp of padding for FABs .navigationBarsPadding() // padding for navigation bar .imePadding(), // padding for when IME appears onClick = { } ) { Icon(imageVector = Icons.Filled.Add, contentDescription = "Add") } } }
![Animación que muestra un elemento de IU que se desplaza desde arriba hacia abajo a fin de dejar lugar para un teclado.](https://developer.android.com/static/develop/ui/compose/images/interop-keyboard.gif?authuser=9&hl=es)
Compatibilidad con la inserción para componentes de Material 3
Para facilitar su uso, muchos de los elementos integrados de Material 3 componibles
(androidx.compose.material3
)
Controlan las inserciones, según cómo se ubican estos elementos en tu app.
según las especificaciones de Material.
Control de inserción de elementos componibles
A continuación, se incluye una lista de Material Componentes que controlar automáticamente las inserciones.
Barras de la app
TopAppBar
/SmallTopAppBar
/CenterAlignedTopAppBar
/MediumTopAppBar
/LargeTopAppBar
: Aplica los lados superior y horizontal de las barras del sistema como relleno, ya que se usa en la parte superior de la ventana.BottomAppBar
: Aplica los lados inferior y horizontal de las barras del sistema como padding.
Contenedores de contenido
ModalDrawerSheet
/DismissibleDrawerSheet
/PermanentDrawerSheet
(contenido dentro de un panel lateral de navegación modal): Aplica las inserciones vertical e de inicio al contenido.ModalBottomSheet
: Aplica las inserciones inferiores.NavigationBar
: Aplica las inserciones inferior y horizontal.NavigationRail
: Aplica las inserciones vertical y inicio.
Scaffold
De forma predeterminada,
Scaffold
proporciona inserciones como el parámetro paddingValues
para que las consumas y las uses.
Scaffold
no aplica las inserciones al contenido. esta responsabilidad es tuya.
Por ejemplo, para consumir estas inserciones con un LazyColumn
dentro de un Scaffold
:
Scaffold { innerPadding -> // innerPadding contains inset information for you to use and apply LazyColumn( // consume insets as scaffold doesn't do it by default modifier = Modifier.consumeWindowInsets(innerPadding), contentPadding = innerPadding ) { items(count = 100) { Box( Modifier .fillMaxWidth() .height(50.dp) .background(colors[it % colors.size]) ) } } }
Anula las inserciones predeterminadas
Puedes cambiar el parámetro windowInsets
que se pasa al elemento componible para
configurar el comportamiento del elemento. Este parámetro puede ser un tipo diferente de
la inserción de ventana para aplicar en su lugar, o la inhabilitación pasa una instancia vacía:
WindowInsets(0, 0, 0, 0)
Por ejemplo, para inhabilitar el manejo de inserciones en
LargeTopAppBar
:
Configura el parámetro windowInsets
en una instancia vacía:
LargeTopAppBar( windowInsets = WindowInsets(0, 0, 0, 0), title = { Text("Hi") } )
Interoperabilidad con las inserciones del sistema de View
Es posible que debas anular las inserciones predeterminadas cuando la pantalla tenga tanto View como Redactar código en la misma jerarquía En este caso, debes ser explícito en cuál debe consumir las inserciones y cuál debe ignorarlas.
Por ejemplo, si tu diseño más externo es de Android View, deberías
consumen las inserciones del sistema de View y las ignoran para Compose.
Como alternativa, si el diseño más externo es un elemento componible, debes consumir el
las inserciones en Compose y rellena los elementos componibles AndroidView
según corresponda.
De forma predeterminada, cada ComposeView
consume todas las inserciones en el
WindowInsetsCompat
nivel de consumo. Para cambiar este comportamiento predeterminado, establece
ComposeView.consumeWindowInsets
a false
.
Recursos
- Now in Android: Es una app para Android completamente funcional compilada por completo con Kotlin y Jetpack Compose.
- Controla las aplicaciones de borde a borde en Android 15: Un codelab en el que se explica la aplicación de borde a borde de Android 15.
- 3 cosas para mejorar la experiencia de tu app para Android: De borde a borde, Atrás predictivo y Vistazo (un video de YouTube en el que se hace referencia a la aplicación de borde a borde de Android 15)
- Inserciones y de borde a borde | Sugerencias de redacción: Un video de YouTube en el que se muestra cómo controlar las inserciones para dibujar de borde a borde
Recomendaciones para ti
- Nota: El texto del vínculo se muestra cuando JavaScript está desactivado
- Componentes y diseños de Material
- Cómo migrar
CoordinatorLayout
a Compose - Otras consideraciones