Fournir un retour arrière personnalisé

Les utilisateurs reviennent en arrière dans les écrans à l'aide de la navigation vers l'arrière. La plupart des appareils Android sont dotés d'un bouton Retour (physique, logiciel ou basé sur un geste). En règle générale, vous ne devez pas ajouter de bouton "Retour" à votre application. Toutefois, les appareils Android Automotive OS (AAOS) en mode compatibilité utilisent un bouton "Retour" système. Cela gère la navigation, vous n'avez donc pas besoin d'en ajouter une. Pour en savoir plus, consultez Mode de compatibilité AAOS.

Android conserve une pile "Retour" des destinations à mesure que l'utilisateur parcourt votre application. Cela permet généralement à Android de naviguer correctement vers les destinations précédentes en appuyant sur le bouton "Retour". Toutefois, dans certains cas, il se peut que votre application doive implémenter son propre comportement "Retour" afin d'offrir la meilleure expérience utilisateur possible. Par exemple, lorsque vous utilisez une WebView, vous pouvez ignorer le comportement par défaut du bouton "Retour" pour permettre à l'utilisateur de revenir dans son historique de navigation Web plutôt que dans les écrans précédents de votre application.

Implémenter une navigation vers l'arrière personnalisée dans Compose

Dans Jetpack Compose, vous pouvez gérer la navigation arrière personnalisée à l'aide du composable BackHandler.

Lorsque vous utilisez Navigation Compose, vous utilisez généralement NavController.navigateUp() ou NavController.popBackStack() pour revenir à l'écran précédent dans la pile "Retour". Toutefois, BackHandler est utile dans les cas où vous souhaitez implémenter un comportement personnalisé lorsque l'utilisateur appuie sur le bouton "Retour" du système ou utilise le geste Retour. Par exemple, si vous affichez un WebView dans votre application, vous pouvez autoriser les utilisateurs à revenir en arrière dans l'historique de navigation lorsqu'ils appuient sur le bouton Retour du système.

Si vous avez plusieurs composables BackHandler activés à différents niveaux de votre arbre de composables, seul le plus intérieur intercepte l'événement de retour.

Implémenter une navigation vers l'arrière personnalisée avec des vues

ComponentActivity, la classe de base pour FragmentActivity et AppCompatActivity, vous permet de contrôler le comportement du bouton "Retour" à l'aide de son OnBackPressedDispatcher, que vous pouvez récupérer en appelant getOnBackPressedDispatcher().

OnBackPressedDispatcher contrôle la façon dont les événements du bouton "Retour" sont envoyés à un ou plusieurs objets OnBackPressedCallback. Le constructeur de OnBackPressedCallback utilise une valeur booléenne pour l'état initial activé. C'est seulement lorsqu'un rappel est activé, par exemple lorsque isEnabled() renvoie la valeur true, que le dispatcher appelle la méthode handleOnBackPressed() du rappel pour gérer l'événement du bouton "Retour". Vous pouvez modifier l'état d'activation en appelant setEnabled().

Les rappels sont ajoutés à l'aide des méthodes addCallback. Utilisez la méthode addCallback(), qui accepte un LifecycleOwner. De cette façon, OnBackPressedCallback n'est ajouté que lorsque LifecycleOwner est défini sur Lifecycle.State.STARTED. L'activité supprime également les rappels enregistrés lorsque le LifecycleOwner associé est détruit. Cela permet d'éviter les fuites de mémoire et de les utiliser dans des fragments ou d'autres propriétaires de cycle de vie ayant une durée de vie plus courte.

Voici un exemple d'implémentation du rappel :

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()
    }
    ...
}

Vous pouvez fournir plusieurs rappels à l'aide de addCallback(). Les rappels sont alors appelés dans l'ordre inverse dans lequel ils sont ajoutés. Le rappel ajouté en dernier est le premier à avoir la possibilité de gérer l'événement du bouton "Retour". Par exemple, si vous avez ajouté trois rappels nommés one, two et three dans l'ordre, ils seront appelés dans l'ordre three, two, et one, respectivement.

Les rappels suivent le schéma de chaîne de responsabilité. Chaque rappel de la chaîne n'est invoqué que si le rappel précédent n'a pas été activé. Cela signifie que dans l'exemple précédent, le rappel two ne sera invoqué que si le rappel three n'est pas activé. Le rappel one ne serait invoqué que si le rappel two n'était pas activé, et ainsi de suite.

Notez que lorsqu'un rappel est ajouté à l'aide de addCallback(), il n'est pas ajouté à la chaîne de responsabilité tant que LifecycleOwner ne passe pas à l'état Lifecycle.State.STARTED.

Il est fortement recommandé de modifier l'état d'activation de OnBackPressedCallback pour les modifications temporaires, car cela conserve l'ordre décrit ci-dessus, ce qui est particulièrement important si vous avez enregistré des rappels pour plusieurs propriétaires de cycle de vie imbriqués différents.

Toutefois, si vous souhaitez supprimer entièrement OnBackPressedCallback, vous devez appeler remove(). Ce n'est généralement pas nécessaire, car les rappels sont automatiquement supprimés lorsque leur LifecycleOwner associé est détruit.