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

El gesto atrás predictivo, una función de navegación por gestos, permite que los usuarios obtengan una vista previa del lugar al que los lleva el deslizamiento 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, ya sea 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 retrocompatible en AndroidX Activity 1.6.0 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 los gestos personalizados para volver en Compose

Compose proporciona la función de componibilidad PredictiveBackHandler para controlar los gestos personalizados para volver atrás. Esta API te permite responder al gesto 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.

Para usar PredictiveBackHandler, asegúrate de que tu app incluya la dependencia androidx.activity:activity-compose (versión 1.8.0 o posterior):

// In your build.gradle.kts file:
dependencies {
    implementation("androidx.activity:activity-compose:1.8.0")
}

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

El gesto atrás predictivo está habilitado de forma predeterminada.

Si tu app usa Fragments o el componente Navigation, también actualiza a AndroidX Activity 1.6.0 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 o una versión posterior.

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

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 con OnBackPressed o KeyEvent.KEYCODE_BACK.

  4. Asegúrate de actualizar a AndroidX Activity 1.6.0 o una versión posterior.

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

Inhabilita 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 estableces este valor como falso, ocurrirá 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 configurado 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 a la API de la plataforma OnBackInvokedCallback. 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.

Lineamientos para las devoluciones de llamadas

Sigue estos lineamientos cuando uses 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 retroceso 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 volver. No crees estas devoluciones de llamada para ejecutar la lógica empresarial ni para registrar.

Usa los siguientes enfoques si tu app debe ejecutar la lógica empresarial o registrar cuando el usuario desliza el dedo hacia atrás:

  • En 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 Compose se quita de la pila de actividades y se destruye.
  • En Android 16 y versiones posteriores: Usa OnBackInvokedCallback con PRIORITY_SYSTEM_NAVIGATION_OBSERVER. 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 desliza el dedo hacia atrás desde la actividad raíz (sale de tu app) para registrar el evento de retroceso o ejecutar la lógica empresarial, mientras se permite que se reproduzca la animación de regreso a la pantalla principal.
  • En las apps basadas en objetos View: Registra dentro de las devoluciones de llamada del ciclo de vida o de la pila de actividades, en lugar de consumir eventos de retroceso:
    • Para las transiciones de actividad, verifica si isFinishing es true en Activity.onDestroy().
    • Para las transiciones de fragmentos, verifica si isRemoving es true dentro del ciclo de vida de la vista del fragmento onDestroy() o usa FragmentManager.OnBackStackChangedListener (onBackStackChangeStarted/onBackStackChangeCommitted).

Crea devoluciones de llamadas de responsabilidad única

Puedes agregar varias devoluciones de llamadas al despachador. 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 en Compose.
Figura 2: Diagrama de la pila de devoluciones de llamada en Compose.

En la Figura 2, se muestra cómo puedes tener varias devoluciones de llamada en la pila, cada una responsable de una tarea. En Compose, las devoluciones de llamada se evalúan desde el elemento componible más interno hasta el más externo, y una devolución de llamada solo se ejecuta si las devoluciones de llamada que la preceden en la pila están inhabilitadas:

  • El mensaje "¿Seguro que…" PredictiveBackHandler se habilita cuando el usuario ingresa datos en un formulario y se inhabilita en caso contrario. Cuando se habilita, intercepta el gesto de atrás para mostrar un diálogo de confirmación o una animación personalizada en la app.
  • La BackHandler a nivel de la pantalla se ejecuta si la devolución de llamada anterior está inhabilitada. En este ejemplo, está inhabilitada.
  • La devolución de llamada NavHost controla la navegación hacia atrás para quitar destinos de la pila de actividades si se inhabilitan las devoluciones de llamada personalizadas anteriores.
  • Por último, el sistema controla el gesto atrás si se inhabilitan todas las devoluciones de llamada anteriores. Cuando la pila de actividades se encuentra en su destino raíz, el sistema activa animaciones a nivel del sistema, como volver a la pantalla principal, cambiar de actividad y cambiar de tarea.

El mismo comportamiento de la pila se aplica en las apps basadas en View: la última devolución de llamada OnBackPressedCallback habilitada que se agregó tiene prioridad, recurre a FragmentManager y, finalmente, al control del sistema para volver atrás.

Prueba la animación del gesto de retroceso predictivo

A partir de Android 15, las animaciones del sistema, como volver a la pantalla principal, cambiar de tarea y cambiar de actividad, están habilitadas de forma predeterminada para las apps que admiten la navegación hacia atrás predictiva. Ya no están detrás de una opción para desarrolladores.

En los dispositivos que ejecutan Android 13 o Android 14, puedes habilitar la opción para desarrolladores y probar la animación para volver a la pantalla principal que se muestra en la Figura 1:

  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.