Cómo agregar compatibilidad para el gesto atrás predictivo

Figura 1: Simulación del aspecto y la experiencia del gesto atrás predictivo en un teléfono

Atrás predictivo, una función de navegación por gestos, permite a los usuarios obtener una vista previa del lugar al que los lleva el gesto de deslizar hacia atrás.

Por ejemplo, con un gesto atrás, se puede mostrar una vista previa animada de la pantalla principal detrás de la app, como se muestra en la simulación de la Figura 1.

A partir de Android 15, la opción para desarrolladores de animaciones de atrás predictivo ya no está disponible. Las animaciones del sistema, como volver a la pantalla principal, cambiar de tarea y cambiar de actividad, ahora aparecen en las apps que habilitaron el gesto atrás predictivo por completo o a nivel de la actividad.

Puedes probar esta animación de regreso a la página principal (como se describe en una sección posterior de esta página).

Para admitir el gesto atrás predictivo, se requiere actualizar la app, con OnBackPressedCallback AppCompat 1.6.0-alpha05 (AndroidX) retrocompatible o una API posterior, o bien con la nueva API de plataforma OnBackInvokedCallback. La mayoría de las apps usan la API de AndroidX retrocompatible.

Esta actualización proporciona una ruta de migración para interceptar correctamente la navegación hacia atrás, lo que implica reemplazar las interceptaciones de retroceso de KeyEvent.KEYCODE_BACK y cualquier clase con métodos onBackPressed, como Activity y Dialog con las nuevas APIs de retroceso del sistema.

Codelab y video de Google I/O

Además de usar la documentación en esta página, prueba nuestro codelab. Este proporciona una implementación de casos de uso común de un WebView que controla el gesto atrás predictivo mediante las APIs de actividad de AndroidX.

También puedes ver nuestro video de Google I/O, que abarca ejemplos adicionales sobre la implementación de AndroidX y las APIs de la plataforma.

Cómo controlar gestos de atrás personalizados en Compose

Compose proporciona el elemento PredictiveBackHandler componible para controlar los gestos de atrás personalizados. Esta API te permite responder al gesto de atrás y proporciona un Flow de objetos BackEventCompat que puedes usar para implementar animaciones o transiciones personalizadas a medida que el usuario desliza el dedo.

PredictiveBackHandler(enabled = isBackHandlerEnabled) { progress: Flow<BackEventCompat> ->
    try {
        progress.collect { backEvent ->
            // Update your UI or animation based on backEvent.progress
        }
        // Handle the final back action (e.g., navigate back)
    } catch (e: CancellationException) {
        // Back gesture was cancelled, reset your UI
    }
}

Si solo necesitas interceptar el gesto de atrás sin hacer un seguimiento del progreso, usa BackHandler.

Actualiza una app que usa la navegación hacia atrás predeterminada

La función Atrás predictivo está habilitada de forma predeterminada.

Si tu app usa Fragments o el componente Navigation, también actualiza a AndroidX Activity 1.6.0-alpha05 o versiones posteriores.

Actualiza una app que usa una navegación hacia atrás personalizada

Si tu app implementa un comportamiento de navegación hacia atrás personalizada, existen diferentes rutas de migración en función de si usa AndroidX y cómo controla este tipo de navegación.

Cómo tu app controla la navegación hacia atrás Ruta de migración recomendada (vínculo en esta página)
APIs de AndroidX Migra una implementación actual de AndroidX
APIs de plataforma no compatibles Migra una app de AndroidX que contiene APIs de navegación hacia atrás no compatibles a las APIs de AndroidX

Migra una implementación de navegación hacia atrás de AndroidX

Este caso de uso es el más común (y el más recomendado). Se aplica a apps nuevas o existentes que implementan el manejo de navegación por gestos personalizada con OnBackPressedDispatcher, como se describe en Cómo brindar navegación personalizada hacia atrás.

Para asegurarte de que las APIs que ya usan OnBackPressedDispatcher (como Fragments y el componente Navigation) funcionen sin problemas con el gesto atrás predictivo, actualiza a AndroidX Activity 1.6.0-alpha05.

```xml
// In your build.gradle file:
dependencies {

// Add this in addition to your other dependencies
implementation "androidx.activity:activity:1.6.0-alpha05"
```

Migra una app de AndroidX que contiene APIs de navegación hacia atrás no compatibles a las APIs de AndroidX

Si tu app usa bibliotecas de AndroidX, pero implementa APIs de navegación hacia atrás no compatibles o hace referencia a estas, deberás migrar al uso de las APIs de AndroidX para admitir el nuevo comportamiento.

Para migrar APIs no compatibles a las APIs de AndroidX, haz lo siguiente:

  1. Migra la lógica del control de navegación hacia atrás del sistema a OnBackPressedDispatcher de AndroidX con una implementación de OnBackPressedCallback. Para obtener ayuda detallada, consulta Cómo brindar navegación hacia atrás personalizada.

  2. Inhabilita OnBackPressedCallback cuando todo esté listo para dejar de interceptar el gesto atrás.

  3. Deja de interceptar eventos de retroceso mediante OnBackPressed o KeyEvent.KEYCODE_BACK.

  4. Asegúrate de actualizar a AndroidX Activity 1.6.0-alpha05.

    // In your build.gradle file:
    dependencies {
    
    // Add this in addition to your other dependencies
    implementation "androidx.activity:activity:1.6.0-alpha05"
    

Cómo inhabilitar el gesto atrás predictivo

Para inhabilitarla, en AndroidManifest.xml, en la etiqueta <application>, establece la marca android:enableOnBackInvokedCallback en false.

<application
    ...
    android:enableOnBackInvokedCallback="false"
    ... >
...
</application>

Si se establece en falso, se realiza lo siguiente:

  • Inhabilita la animación de gesto atrás predictivo del sistema.
  • Ignora OnBackInvokedCallback, pero las llamadas OnBackPressedCallback siguen funcionando.

Inhabilita el gesto a nivel de la actividad

La marca android:enableOnBackInvokedCallback te permite inhabilitar las animaciones predictivas del sistema a nivel de la actividad. Este comportamiento facilita la migración de apps grandes de varias actividades a gestos atrás predictivos.

En el siguiente código, se muestra un ejemplo de enableOnBackInvokedCallback establecido para habilitar la animación del sistema para volver a la pantalla principal desde MainActivity:

<manifest ...>
    <application . . .

        android:enableOnBackInvokedCallback="false">

        <activity
            android:name=".MainActivity"
            android:enableOnBackInvokedCallback="true"
            ...
        </activity>
        <activity
            android:name=".SecondActivity"
            android:enableOnBackInvokedCallback="false"
            ...
        </activity>
    </application>
</manifest>

Ten en cuenta las siguientes consideraciones cuando uses la marca android:enableOnBackInvokedCallback:

  • Cuando se configura android:enableOnBackInvokedCallback=false, se desactivan las animaciones del gesto atrás predictivo a nivel de la actividad o de la app, según el lugar en el que establezcas la etiqueta, y le indica al sistema que ignore las llamadas al OnBackInvokedCallback de la API de la plataforma. Sin embargo, las llamadas a OnBackPressedCallback se siguen ejecutando porque OnBackPressedCallback es retrocompatible y llama a la API de onBackPressed, que no era compatible con versiones anteriores a Android 13.
  • Cuando se configura la marca enableOnBackInvokedCallback a nivel de la app, se establece el valor predeterminado para todas las actividades de la app. Puedes anular el valor predeterminado por actividad si configuras la marca a nivel de la actividad, como se muestra en el ejemplo de código anterior.

Prácticas recomendadas para devolución de llamadas

Estas son las prácticas recomendadas para usar las devoluciones de llamadas del sistema compatibles: PredictiveBackHandler o BackHandler (para Compose), OnBackPressedCallback o OnBackInvokedCallback.

Determina el estado de la IU que habilita o inhabilita cada devolución de llamada

El estado de la IU es la propiedad que describe la IU. Te recomendamos que sigas estos pasos de alto nivel.

  1. Determina el estado de la IU que habilita o inhabilita cada devolución de llamada.

  2. Define ese estado con un tipo de contenedor de datos observables, como StateFlow o Compose State, y habilita o inhabilita la devolución de llamada a medida que cambia el estado.

Si tu app antes asociaba la lógica de atrás con sentencias condicionales, esto podría significar que reaccionas al evento de atrás después de que ya ocurrió. Evita este patrón con devoluciones de llamada más recientes. Si es posible, mueve la devolución de llamada fuera de la sentencia condicional y, en su lugar, asóciala a un tipo de contenedor de datos observables.

Usa devoluciones de llamada hacia atrás del sistema para la lógica de la IU

La lógica de la IU determina cómo mostrar la IU. Usa devoluciones de llamada hacia atrás del sistema para ejecutar la lógica de la IU, como mostrar un diálogo o ejecutar una animación.

Si tu app habilita un OnBackPressedCallback o un OnBackInvokedCallback con PRIORITY_DEFAULT o PRIORITY_OVERLAY, las animaciones de atrás predictivo no se ejecutarán y deberás controlar el evento de atrás. No crees estas devoluciones de llamadas para ejecutar lógica empresarial ni para registrar.

Usa los siguientes enfoques si tu app debe ejecutar lógica empresarial o registrar cuando el usuario desliza el dedo para volver:

  • Usa OnBackInvokedCallback con PRIORITY_SYSTEM_NAVIGATION_OBSERVER en dispositivos con Android 16 y versiones posteriores. Esto crea una devolución de llamada del observador que no consume el evento de atrás. Por ejemplo, puedes registrar esta devolución de llamada cuando el usuario deslice el dedo para volver desde la actividad raíz o, en otras palabras, cuando el usuario haya salido de tu app. En este caso, puedes registrar el evento de volver o ejecutar otra lógica empresarial, y la animación de atrás para volver a la pantalla principal seguirá reproduciéndose.
  • Para casos de actividad a actividad o de fragmento a actividad, registra si isFinishing dentro de onDestroy es true en el ciclo de vida de la actividad.
  • Para casos de fragmento a fragmento, registra si isRemoving dentro de onDestroy es verdadero dentro del ciclo de vida de la vista del fragmento. O bien, registra con los métodos onBackStackChangeStarted o onBackStackChangeCommitted dentro de FragmentManager.OnBackStackChangedListener.
  • En el caso de Compose, registra en la devolución de llamada onCleared() de un ViewModel asociado con el destino de Compose. Este es el mejor indicador para saber cuándo un destino de composición se quita de la pila de actividades y se destruye.

Crea devoluciones de llamadas de responsabilidad única

Puedes agregar varias devoluciones de llamadas al dispatcher. Las devoluciones de llamada se agregan a una pila en la que la devolución de llamada recién agregada controla el siguiente gesto atrás con una devolución de llamada por gesto atrás.

Es más fácil administrar el estado habilitado de una devolución de llamada si esta tiene una sola responsabilidad. Por ejemplo:

Orden de las devoluciones de llamada en una pila.
Figura 2: Diagrama de pila de devolución de llamada.

En la figura 2, se muestra cómo puedes tener varias devoluciones de llamada en la pila, cada una responsable de una tarea. Una devolución de llamada solo se ejecuta si las devoluciones de llamada que se encuentran sobre ella en la pila están inhabilitadas. En este ejemplo, la devolución de llamada "¿Seguro que deseas...?" se habilita cuando el usuario ingresa datos en un formulario y se inhabilita en cualquier otro caso. La devolución de llamada abre un diálogo de confirmación cuando el usuario desliza el dedo hacia atrás para salir del formulario.

La otra devolución de llamada puede incluir un componente de Material que admita el atrás predictivo, una transición de AndroidX que use las APIs de Progress o alguna otra devolución de llamada personalizada.

El mismo comportamiento de la pila se aplica en Compose: el PredictiveBackHandler o BackHandler más interno tiene prioridad.

Del mismo modo, se ejecuta la devolución de llamada de childFragmentManager si las devoluciones de llamada anteriores están inhabilitadas y la pila de actividades de este FragmentManager no está vacía. En este ejemplo, esta devolución de llamada interna está inhabilitada.

Del mismo modo, la devolución de llamada interna de supportFragmentManager se ejecuta si las devoluciones de llamada anteriores están inhabilitadas y su pila no está vacía. En este ejemplo, esta devolución de llamada se ejecuta si el usuario no ingresó texto en el formulario, lo que provoca que se inhabilite la devolución de llamada "¿Seguro que deseas...?".

Por último, el sistema controla el gesto de atrás si las devoluciones de llamada anteriores están inhabilitadas. Para activar animaciones del sistema, como volver a la pantalla principal, cambiar de actividad y cambiar de tarea, la pila de actividades de supportFragmentManager debe estar vacía para que su devolución de llamada interna esté inhabilitada.

Prueba la animación del gesto de retroceso predictivo

Si aún usas Android 13 o Android 14, puedes probar la animación para volver a la pantalla principal que se muestra en la Figura 1.

Para probar esta animación, sigue estos pasos:

  1. En tu dispositivo, ve a Configuración > Sistema > Opciones para desarrolladores.

  2. Selecciona Animaciones del gesto atrás predictivo.

  3. Inicia la app actualizada y usa el gesto de retroceso para verlo en acción.