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, por lo que tu app no debería incluirlo en la IU. 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. Por lo general, 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 a fin de 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.

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

ComponentActivity, la clase base de FragmentActivity y AppCompatActivity, te permite controlar el comportamiento del botón Atrás usando su OnBackPressedDispatcher, que puedes recuperar 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. Solo cuando se habilita una devolución de llamada (es decir, cuando el objeto 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 llamadas se agregan a través de los métodos addCallback. Te recomendamos que uses el método addCallback(), que toma un objeto 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 lo utilice en fragmentos y otros propietarios del ciclo de vida con tiempos de vida más cortos que la actividad.

El siguiente es un ejemplo de implementación de devolución de llamada:

Kotlin

class MyFragment : Fragment() {

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

        // This callback will only be 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 will only be 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 llamada 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, respectivamente.

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. La devolución de llamada one solo se invoca si la devolución de llamada two no estaba habilitada, y así sucesivamente.

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

Se recomienda 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.

Sin embargo, 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.