Cómo brindar navegación de retroceso personalizada

La navegación hacia atrás hace referencia a cómo los usuarios navegan de manera inversa por el historial de pantallas que visitaron anteriormente. Todos los dispositivos Android incluyen un botón Atrás para este tipo de navegación, así que no incluyas el botón Atrás a la IU de tu app. Según el dispositivo Android del usuario, este botón puede ser un botón físico o de software.

Android mantiene una pila de actividades de destinos a medida que el usuario navega por tu aplicación. Esto permite que Android navegue correctamente a destinos anteriores cuando se presiona el botón Atrás. Sin embargo, hay algunos casos en los que tu app podría necesitar implementar su propio comportamiento del botón Atrás para brindar una mejor experiencia del usuario.

Por ejemplo, cuando usas un objeto WebView, es posible que te convenga anular el comportamiento predeterminado del botón Atrás de modo que se le permita al usuario navegar hacia atrás en su historial de navegación web en lugar de las pantallas anteriores en tu app.

Android 13 y versiones posteriores incluyen un gesto atrás predictivo para dispositivos Android. Para obtener más información acerca de esta función, consulta Cómo agregar compatibilidad con el gesto atrás predictivo.

Cómo implementar la navegación hacia atrás personalizada

ComponentActivity, la clase de base para FragmentActivity y AppCompatActivity, te permite controlar el comportamiento del botón Atrás con su OnBackPressedDispatcher, al que puedes acceder llamando a getOnBackPressedDispatcher().

El elemento OnBackPressedDispatcher controla cómo se despachan los eventos del botón Atrás a uno o más objetos OnBackPressedCallback. El constructor de OnBackPressedCallback toma un valor booleano para el estado habilitado inicial. Cuando se habilita una devolución de llamada, esto es cuando isEnabled() muestra true, el despachador llama al handleOnBackPressed() de la devolución de llamada para controlar el evento del botón Atrás. Puedes llamar a setEnabled() para cambiar el estado habilitado.

Las devoluciones de llamada se agregan a través de los métodos addCallback. Te recomendamos que uses el método addCallback(), que toma un LifecycleOwner. De esta manera, se garantiza que el OnBackPressedCallback solo se agregue cuando el objeto LifecycleOwner sea Lifecycle.State.STARTED. La actividad también quita las devoluciones de llamada registradas cuando se destruye su objeto LifecycleOwner asociado, lo que evita fugas de memoria y permite que se utilice LifecycleOwner en fragmentos y otros propietarios del ciclo de vida con tiempos de vida más cortos que la actividad.

Aquí se muestra un ejemplo de una implementación de devolución de llamada:

Kotlin

class MyFragment : Fragment() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        // This callback is only called when MyFragment is at least started
        val callback = requireActivity().onBackPressedDispatcher.addCallback(this) {
            // Handle the back button event
        }

        // The callback can be enabled or disabled here or in the lambda
    }
    ...
}

Java

public class MyFragment extends Fragment {

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // This callback is only called when MyFragment is at least started
        OnBackPressedCallback callback = new OnBackPressedCallback(true /* enabled by default */) {
            @Override
            public void handleOnBackPressed() {
                // Handle the back button event
            }
        };
        requireActivity().getOnBackPressedDispatcher().addCallback(this, callback);

        // The callback can be enabled or disabled here or in handleOnBackPressed()
    }
    ...
}

Puedes proporcionar varias devoluciones de llamadas a través de addCallback(). Cuando lo haces, las devoluciones de llamada se invocan en el orden inverso del que se agregaron. La última devolución de llamada que se agregó es la primera que tiene la oportunidad de controlar el evento del botón Atrás. Por ejemplo, si agregaste tres devoluciones de llamada con los nombres one, two y three en ese orden, se invocarán en el orden de three, two y one.

Las devoluciones de llamadas siguen el patrón de la Cadena de responsabilidad. Cada devolución de llamada en la cadena se invoca solo si la devolución de llamada anterior no estaba habilitada. Eso quiere decir que, en el ejemplo anterior, la devolución de llamada two solo se invoca si la devolución de llamada three no estaba habilitada y la devolución de llamada one solo se invoca si la devolución de llamada two no estaba habilitada.

Ten en cuenta que cuando la devolución de llamada se agrega a través de addCallback(), no se agrega a la cadena de responsabilidad hasta que LifecycleOwner pasa al estado Lifecycle.State.STARTED.

Te recomendamos que cambies el estado habilitado en el objeto OnBackPressedCallback para los cambios temporales, ya que mantiene el orden descrito anteriormente. Esto es importante, en especial, si tienes devoluciones de llamada registradas en varios propietarios del ciclo de vida anidados.

Si deseas quitar el objeto OnBackPressedCallback por completo, debes llamar a remove(). Por lo general, no es necesario, ya que las devoluciones de llamada se quitan automáticamente cuando se destruye su elemento LifecycleOwner asociado.

Actividad onBackPressed()

Si usas onBackPressed() para controlar los eventos del botón Atrás, te recomendamos que utilices OnBackPressedCallback en su lugar. Sin embargo, si no puedes hacer este cambio, se aplican las siguientes reglas:

  • Todas las devoluciones de llamada registradas a través de addCallback se evalúan cuando llamas a super.onBackPressed().
  • En Android 12 (nivel de API 32) y versiones anteriores, siempre se llama a onBackPressed, independientemente de las instancias registradas de OnBackPressedCallback.