299 votes

Comment effacer la pile de navigation après avoir navigué vers un autre fragment dans Android

Je suis l'aide de La nouvelle Architecture de Navigation Composant dans android et je suis coincé à la destruction de la pile de navigation après le déménagement vers un nouveau fragment.

Exemple: Je suis dans le loginFragment et je veux que ce fragment être nettoyée de la pile lorsque je navigue à la maison fragment de sorte que l'utilisateur ne sera pas retourné à la loginFragment quand il appuie sur le bouton retour.

Je suis à l'aide d'un simple NavHostFragment.findNavController(Fragment).naviguer(R. id.homeFragment) pour naviguer.

Code Actuel :

mAuth.signInWithCredential(credential)
            .addOnCompleteListener(getActivity(), new OnCompleteListener<AuthResult>() {
                @Override
                public void onComplete(@NonNull Task<AuthResult> task) {
                    if (task.isSuccessful()) {
                        NavHostFragment.findNavController(LoginFragment.this).navigate(R.id.homeFragment);
                    } else {
                        Log.w(TAG, "signInWithCredential:failure", task.getException());
                    }
                }
            });

J'ai essayé d'utiliser le NavOptions dans la navigation(), mais le bouton de retour est toujours de m'envoyer retour à la loginFragment

NavOptions.Builder navBuilder = new NavOptions.Builder();
NavOptions navOptions = navBuilder.setPopUpTo(R.id.homeFragment, false).build();   
             NavHostFragment.findNavController(LoginFragment.this).navigate(R.id.homeFragment, null, navOptions);

423voto

Subhojit Shaw Points 1369

Tout d'abord, ajouter des attributs app:popUpTo='your_nav_graph_id' et app:popUpToInclusive="true" pour l'action de la balise.

<fragment
    android:id="@+id/signInFragment"
    android:name="com.glee.incog2.android.fragment.SignInFragment"
    android:label="fragment_sign_in"
    tools:layout="@layout/fragment_sign_in" >
    <action
        android:id="@+id/action_signInFragment_to_usersFragment"
        app:destination="@id/usersFragment"
        app:launchSingleTop="true"
        app:popUpTo="@+id/main_nav_graph"
        app:popUpToInclusive="true" />
</fragment>

Deuxièmement, naviguer jusqu'à la destination, à l'aide de action ci-dessus en tant que paramètre.

findNavController(fragment).navigate(
     SignInFragmentDirections.actionSignInFragmentToUserNameFragment())

Voir les docs pour plus d'informations.

REMARQUE: Si vous naviguez à l'aide de la méthode navigate(@IdRes int resId), vous ne pourrez pas obtenir le résultat souhaité. Donc, j'ai utilisé la méthode navigate(@NonNull NavDirections directions).

105voto

dongkichan Points 111

Je pense que votre question concernent spécifiquement sur la façon d'utiliser le menu de Comportement / Pop / app:popUpTo (en xml)

Dans la documentation,
Pop jusqu'à une destination donnée avant la navigation. Ceci ouvre tous les non-correspondance des destinations à partir de l'arrière de la pile jusqu'à ce que cette destination est trouvée.

Exemple (Simple Travail de chasse app)
mon start_screen_nav graphique est comme ceci:

startScreenFragment (start) -> loginFragment -> EmployerMainFragment

                            -> loginFragment -> JobSeekerMainFragment

si je veux naviguer EmployerMainFragment et pop de tous , y compris startScreenFragment le code sera:

        <action
            android:id="@+id/action_loginFragment_to_employerMainFragment"
            app:destination="@id/employerMainFragment"

            app:popUpTo="@+id/startScreenFragment"
            app:popUpToInclusive="true" />

si je veux naviguer EmployerMainFragment et de la pop tout en excluant startScreenFragment le code sera:

        <action
            android:id="@+id/action_loginFragment_to_employerMainFragment"
            app:destination="@id/employerMainFragment"

            app:popUpTo="@+id/startScreenFragment"/>

si je veux naviguer EmployerMainFragment et pop - loginFragment mais pas startScreenFragment le code sera:

        <action
            android:id="@+id/action_loginFragment_to_employerMainFragment"
            app:destination="@id/employerMainFragment"

            app:popUpTo="@+id/loginFragment"
            app:popUpToInclusive="true"/>

OU

        <action
            android:id="@+id/action_loginFragment_to_employerMainFragment"
            app:destination="@id/employerMainFragment"

            app:popUpTo="@+id/startScreenFragment"/>

77voto

Nour Ahmed Points 117

Dans mon cas, je devais tout supprimer dans la pile arrière avant d'ouvrir un nouveau fragment, j'ai donc utilisé ce code

 navController.popBackStack(R.id.fragment_apps, true);
navController.navigate(R.id.fragment_company);
 

la première ligne supprime la pile arrière jusqu'à ce qu'elle atteigne le fragment spécifié dans mon cas, c'est le fragment d'origine, donc elle supprime complètement toute la pile arrière, et lorsque l'utilisateur clique de nouveau dans la société fragment_, il ferme l'application.

16voto

Mel Points 476

REMARQUE: Effacer la tâche est obsolète, description officielle est

Cette méthode est obsolète. Utilisation setPopUpTo(int, boolean) avec l'id de la NavController du graphique et de l'ensemble inclusive pour vrai.

Vieille Réponse

Si vous ne voulez pas passer par tout ce que fuzz dans le code, vous pouvez simplement cocher Clear Task en Launch Options dans les propriétés de l'action.

Launch Options

Edit: Comme d'Android Studio 3.2 Beta 5, Effacer la Tâche est plus visible dans les Options de Lancement de la fenêtre, mais vous pouvez toujours l'utiliser dans la navigation du code XML, dans l'action de la balise, en ajoutant

app:clearTask="true"

11voto

Youssef El Behi Points 185

Je l'ai enfin compris grâce à Comment désactiver UP dans la navigation pour certains fragments avec le nouveau composant d'architecture de navigation?

J'ai dû spécifier .setClearTask (true) comme NavOption.

 mAuth.signInWithCredential(credential)
            .addOnCompleteListener(getActivity(), new OnCompleteListener<AuthResult>() {
                @Override
                public void onComplete(@NonNull Task<AuthResult> task) {
                    if (task.isSuccessful()) {
                        Log.d(TAG, "signInWithCredential:success");


                        NavOptions.Builder navBuilder = new NavOptions.Builder();
                        NavOptions navOptions = navBuilder.setClearTask(true).build();
                        NavHostFragment.findNavController(LoginFragment.this).navigate(R.id.homeFragment,null,navOptions);
                    } else {
                        Log.w(TAG, "signInWithCredential:failure", task.getException());

                    }

                }
            });
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X