Una vez que segmentes el SDK 35 o versiones posteriores en un dispositivo que ejecute Android 15 o versiones posteriores, tu app se mostrará de borde a borde. La ventana abarca todo el ancho y la altura de la pantalla dibujando detrás de las barras del sistema. Las barras del sistema incluyen la barra de estado, la barra de subtítulos y la barra de navegación.
Muchas apps tienen una barra de la app superior. La barra de la app superior debe extenderse hasta el borde superior de la pantalla y mostrarse detrás de la barra de estado. De manera opcional, la barra de la app superior puede reducirse a la altura de la barra de estado cuando se desplaza el contenido.
Muchas apps también tienen una barra de la app inferior o una barra de navegación inferior. Estas barras también deben extenderse hasta el borde inferior de la pantalla y mostrarse detrás de la barra de navegación. De lo contrario, las apps deben mostrar el contenido desplazable detrás de la barra de navegación.
Cuando implementes un diseño de borde a borde en tu app, ten en cuenta lo siguiente:
- Habilita una pantalla de borde a borde.
- Implementa diseños adaptables para optimizar la experiencia del usuario en diferentes factores de forma.
- Controla cualquier superposición visual.
- Considera mostrar velos detrás de las barras del sistema.
Habilita la pantalla de borde a borde
Si tu app se orienta al SDK 35 o versiones posteriores, el diseño de borde a borde se habilita automáticamente para dispositivos con Android 15 o versiones posteriores.
Para habilitar el diseño de borde a borde en versiones anteriores de Android, llama manualmente a
enableEdgeToEdge en onCreate de tu Activity.
Kotlin
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
WindowCompat.enableEdgeToEdge(window)
...
}
Java
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
WindowCompat.enableEdgeToEdge(getWindow());
...
}
De forma predeterminada, enableEdgeToEdge() hace que las barras del sistema sean transparentes, excepto en el modo de navegación con 3 botones, en el que la barra de navegación obtiene un velo traslúcido. Los colores de los íconos del sistema y el velo se ajustan según el tema claro u oscuro del sistema.
Para habilitar la pantalla de borde a borde en tu app sin usar la
enableEdgeToEdge() función, consulta
Cómo configurar manualmente la pantalla de borde a borde.
Controla las superposiciones con inserciones
Es posible que algunas vistas de tu app se dibujen detrás de las barras del sistema, como se muestra en la figura 3.
Puedes abordar las superposiciones reaccionando a las inserciones, que especifican qué partes de la pantalla se cruzan con la IU del sistema, como la barra de navegación o la barra de estado. La intersección puede significar mostrarse sobre el contenido, pero también puede informar a tu app sobre los gestos del sistema.
Los tipos de inserciones que se aplican a la visualización de tu app de borde a borde son los siguientes:
Inserciones de barras del sistema: Son las mejores para las vistas que se pueden presionar y que no deben estar ocultas visualmente por las barras del sistema.
Inserciones de corte de pantalla: Son para áreas en las que puede haber un corte de pantalla debido a la forma del dispositivo.
Inserciones de gestos del sistema: Son para áreas de navegación por gestos que usa el sistema y que tienen prioridad sobre tu app.
Inserciones de barras del sistema
Las inserciones de barras del sistema son el tipo de inserciones de uso frecuente. Representan el área en la que la IU del sistema se muestra en el eje Z sobre tu app. Se usan mejor para mover o rellenar vistas en tu app que se pueden presionar y que no deben estar ocultas visualmente por las barras del sistema.
Por ejemplo, el botón de acción flotante (BAF) de la figura 3 está parcialmente oculto por la barra de navegación:
Para evitar este tipo de superposición visual en el modo de gestos o de botones, puedes aumentar los márgenes de la vista con getInsets(int) y WindowInsetsCompat.Type.systemBars().
En el siguiente ejemplo de código, se muestra cómo implementar inserciones de barras del sistema:
Kotlin
ViewCompat.setOnApplyWindowInsetsListener(fab) { v, windowInsets -> val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars()) // Apply the insets as a margin to the view. This solution sets // only the bottom, left, and right dimensions, but you can apply whichever // insets are appropriate to your layout. You can also update the view padding // if that's more appropriate. v.updateLayoutParams<MarginLayoutParams> { leftMargin = insets.left bottomMargin = insets.bottom rightMargin = insets.right } // Return CONSUMED if you don't want the window insets to keep passing // down to descendant views. WindowInsetsCompat.CONSUMED }
Java
ViewCompat.setOnApplyWindowInsetsListener(fab, (v, windowInsets) -> { Insets insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars()); // Apply the insets as a margin to the view. This solution sets only the // bottom, left, and right dimensions, but you can apply whichever insets are // appropriate to your layout. You can also update the view padding if that's // more appropriate. MarginLayoutParams mlp = (MarginLayoutParams) v.getLayoutParams(); mlp.leftMargin = insets.left; mlp.bottomMargin = insets.bottom; mlp.rightMargin = insets.right; v.setLayoutParams(mlp); // Return CONSUMED if you don't want the window insets to keep passing // down to descendant views. return WindowInsetsCompat.CONSUMED; });
Si aplicas esta solución al ejemplo que se muestra en la figura 3, no se produce ninguna superposición visual en el modo de botones, como se muestra en la figura 4:
Lo mismo se aplica al modo de navegación por gestos, como se muestra en la figura 5:
Inserciones de corte de pantalla
Algunos dispositivos tienen cortes de pantalla. Por lo general, el corte se encuentra en la parte superior de la pantalla y se incluye en la barra de estado. Cuando la pantalla del dispositivo está en modo horizontal, el corte puede estar en el borde vertical. Según el contenido que muestre tu app en la pantalla, debes implementar el padding para evitar los cortes de pantalla, ya que, de forma predeterminada, las apps se dibujarán en el corte de pantalla.
Por ejemplo, muchas pantallas de apps muestran una lista de elementos. No ocultes los elementos de la lista con el corte de pantalla ni las barras del sistema.
Kotlin
ViewCompat.setOnApplyWindowInsetsListener(binding.recyclerView) { v, insets -> val bars = insets.getInsets( WindowInsetsCompat.Type.systemBars() or WindowInsetsCompat.Type.displayCutout() ) v.updatePadding( left = bars.left, top = bars.top, right = bars.right, bottom = bars.bottom, ) WindowInsetsCompat.CONSUMED }
Java
ViewCompat.setOnApplyWindowInsetsListener(mBinding.recyclerView, (v, insets) -> { Insets bars = insets.getInsets( WindowInsetsCompat.Type.systemBars() | WindowInsetsCompat.Type.displayCutout() ); v.setPadding(bars.left, bars.top, bars.right, bars.bottom); return WindowInsetsCompat.CONSUMED; });
Para determinar el valor de WindowInsetsCompat, toma el o lógico de las barras del sistema y los tipos de corte de pantalla.
Establece clipToPadding en RecyclerView para que el padding se desplace con los elementos de la lista. Esto permite que los elementos queden detrás de las barras del sistema cuando el usuario se desplaza, como se muestra en el siguiente ejemplo.
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
Inserciones de gestos del sistema
Las inserciones de gestos del sistema representan las áreas de la ventana en las que los gestos del sistema tienen prioridad sobre tu app. Estas áreas se muestran en naranja en la figura 6:
Al igual que las inserciones de barras del sistema, puedes evitar superponer las inserciones de gestos del sistema
con
getInsets(int)
y
WindowInsetsCompat.Type.systemGestures().
Usa estas inserciones para mover o rellenar vistas deslizables lejos de los bordes. Los casos de uso comunes incluyen hojas inferiores,
deslizamientos en juegos y carruseles implementados con
ViewPager2.
En Android 10 o versiones posteriores, las inserciones de gestos del sistema contienen una inserción inferior para el gesto de inicio y una inserción izquierda y derecha para los gestos de retroceso:
En el siguiente ejemplo de código, se muestra cómo implementar inserciones de gestos del sistema:
Kotlin
ViewCompat.setOnApplyWindowInsetsListener(view) { view, windowInsets -> val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemGestures()) // Apply the insets as padding to the view. Here, set all the dimensions // as appropriate to your layout. You can also update the view's margin if // more appropriate. view.updatePadding(insets.left, insets.top, insets.right, insets.bottom) // Return CONSUMED if you don't want the window insets to keep passing down // to descendant views. WindowInsetsCompat.CONSUMED }
Java
ViewCompat.setOnApplyWindowInsetsListener(view, (v, windowInsets) -> { Insets insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemGestures()); // Apply the insets as padding to the view. Here, set all the dimensions // as appropriate to your layout. You can also update the view's margin if // more appropriate. view.setPadding(insets.left, insets.top, insets.right, insets.bottom); // Return CONSUMED if you don't want the window insets to keep passing down // to descendant views. return WindowInsetsCompat.CONSUMED; });
Componentes de Material
Muchos componentes de Material de Android basados en vistas
(com.google.android.material) controlan automáticamente las inserciones, incluidos
BottomAppBar,
BottomNavigationView,
NavigationRailView
y NavigationView
Sin embargo, AppBarLayout
no controla automáticamente las inserciones. Agrega
android:fitsSystemWindows="true"
para controlar las inserciones superiores.
Lee cómo controlar las inserciones con componentes de Material en Compose.
Envío de inserciones retrocompatible
Para detener el envío de inserciones a las vistas secundarias y evitar el relleno excesivo, puedes
consumir inserciones con la
WindowInsetsCompat.CONSUMED
constante. Sin embargo, en dispositivos que ejecutan Android 10 (nivel de API 29 y versiones anteriores), las inserciones no se envían a los elementos del mismo nivel después de llamar a WindowInsetsCompat.CONSUMED, lo que puede provocar una superposición visual no deseada.
Para confirmar que las inserciones se envían a los elementos del mismo nivel para todas las versiones compatibles de Android, usa ViewGroupCompat#installCompatInsetsDispatch antes de consumir
inserciones, disponibles en
AndroidX Core y Core-ktx 1.16.0-alpha01
y versiones posteriores.
Kotlin
// Use the i.d. assigned to your layout's root view, e.g. R.id.main val rootView = findViewById(R.id.main) // Call before consuming insets ViewGroupCompat.installCompatInsetsDispatch(rootView)
Java
// Use the i.d. assigned to your layout's root view, e.g. R.id.main LinearLayout rootView = findViewById(R.id.main); // Call before consuming insets ViewGroupCompat.installCompatInsetsDispatch(rootView);
Modo envolvente
Es mejor experimentar cierto contenido en pantalla completa, lo que le brinda al usuario una experiencia más envolvente. Puedes ocultar las barras del sistema para el modo envolvente con
las WindowInsetsController
y
WindowInsetsControllerCompat
bibliotecas:
Kotlin
val windowInsetsController = WindowCompat.getInsetsController(window, window.decorView) // Hide the system bars. windowInsetsController.hide(Type.systemBars()) // Show the system bars. windowInsetsController.show(Type.systemBars())
Java
Window window = getWindow(); WindowInsetsControllerCompat windowInsetsController = WindowCompat.getInsetsController(window, window.getDecorView()); if (windowInsetsController == null) { return; } // Hide the system bars. windowInsetsController.hide(WindowInsetsCompat.Type.systemBars()); // Show the system bars. windowInsetsController.show(WindowInsetsCompat.Type.systemBars());
Consulta Oculta las barras del sistema para el modo envolvente para obtener más información sobre la implementación de esta función.
Íconos de la barra del sistema
Llamar a enableEdgeToEdge garantiza que los colores de los íconos de la barra del sistema se actualicen cuando cambia el tema del dispositivo.
Mientras usas el diseño de borde a borde, es posible que debas actualizar manualmente los colores de los íconos de la barra del sistema para que contrasten con el fondo de tu app. Por ejemplo, para crear íconos de barra de estado claros, haz lo siguiente:
Kotlin
WindowCompat.getInsetsController(window, window.decorView) .isAppearanceLightStatusBars = false
Java
WindowCompat.getInsetsController(window, window.getDecorView()) .setAppearanceLightStatusBars(false);
Protección de la barra del sistema
Una vez que tu app se oriente al SDK 35 o versiones posteriores, se aplicará el diseño de borde a borde.
La barra de estado del sistema y las barras de navegación por gestos son transparentes, pero la barra de navegación con tres botones es traslúcida. Llama a enableEdgeToEdge para que sea retrocompatible.
Sin embargo, es posible que los valores predeterminados del sistema no funcionen para todos los casos de uso. Consulta la guía de diseño de barras del sistema de Android y el diseño de borde a borde para determinar si usar barras del sistema transparentes o traslúcidas.
Crea barras del sistema transparentes
Para crear una barra de estado transparente, segmenta Android 15 (SDK 35) o versiones posteriores, o llama a enableEdgeToEdge() con argumentos predeterminados para versiones anteriores.
Para crear una barra de navegación por gestos transparente, segmenta Android 15 o versiones posteriores, o llama a enableEdgeToEdge() con argumentos predeterminados para versiones anteriores. Para la barra de navegación con tres botones, establece Window.setNavigationBarContrastEnforced
en false. De lo contrario, se aplicará un velo traslúcido.
Crea barras del sistema traslúcidas
Para crear una barra de estado traslúcida, haz lo siguiente:
- Actualiza tu dependencia
androidx-corea 1.16.0-beta01 o versiones posteriores. - Encapsula tu diseño XML en
androidx.core.view.insets.ProtectionLayouty asigna un ID. - Accede de forma programática a
ProtectionLayoutpara establecer protecciones, especificando el lado y unGradientProtectionpara la barra de estado.
<androidx.core.view.insets.ProtectionLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/list_protection" android:layout_width="match_parent" android:layout_height="match_parent"> <ScrollView android:id="@+id/item_list" android:clipToPadding="false" android:layout_width="match_parent" android:layout_height="match_parent"> <!--items--> </ScrollView> </androidx.core.view.insets.ProtectionLayout>
findViewById<ProtectionLayout>(R.id.list_protection) .setProtections( listOf( GradientProtection( WindowInsetsCompat.Side.TOP, // Ideally, this is the pane's background color paneBackgroundColor ) ) )
Asegúrate de que el ColorInt que se pasa a GradientProtection coincida con el fondo del contenido. Por ejemplo, un diseño de lista-detalles que se muestra en un dispositivo plegable podría tener diferentes GradientProtections de diferentes colores para el panel de lista y el panel de detalles.
No crees una barra de navegación por gestos traslúcida. Para crear una barra de navegación con tres botones traslúcida, haz una de las siguientes acciones:
- Si ya tienes tu diseño encapsulado en un
ProtectionView, puedes pasar unColorProtectionoGradientProtectionadicional al métodosetProtections. Antes de hacerlo, asegúrate de quewindow.isNavigationBarContrastEnforced = false. - De lo contrario, establece
window.isNavigationBarContrastEnforced = true.
Otras sugerencias
Sugerencias adicionales para controlar las inserciones.
Haz que el contenido desplazable sea de borde a borde
Para asegurarte de que el último elemento de la lista no esté oculto por las barras del sistema en tu RecyclerView o NestedScrollView, controla las inserciones y establece clipToPadding en false.
En el siguiente video, se muestra un RecyclerView con la pantalla de borde a borde inhabilitada (izquierda) y habilitada (derecha):
Consulta los fragmentos de código en la sección Cómo crear listas dinámicas con RecyclerView para obtener una muestra de código.
Haz que los diálogos de pantalla completa sean de borde a borde
Para que los diálogos de pantalla completa sean de borde a borde, llama a enableEdgeToEdge en el diálogo.
Kotlin
class MyAlertDialogFragment : DialogFragment() {
override fun onStart(){
super.onStart()
dialog?.window?.let { WindowCompat.enableEdgeToEdge(it) }
}
...
}
Java
public class MyAlertDialogFragment extends DialogFragment {
@Override
public void onStart() {
super.onStart();
Dialog dialog = getDialog();
if (dialog != null) {
Window window = dialog.getWindow();
if (window != null) {
WindowCompat.enableEdgeToEdge(window);
}
}
}
...
}
Recursos adicionales
Consulta las siguientes referencias para obtener más información sobre el diseño de borde a borde.
Blogs
- Sugerencias para controlar las inserciones para la aplicación de borde a borde de Android 15
- WindowInsets: Objetos de escucha y diseños
Diseño
Otra documentación
Videos