web-dev-qa-db-fra.com

Comment effacer la navigation Pile après avoir accédé à un autre fragment dans Android

J'utilise la nouvelle composant d'architecture de navigation dans Android et je suis coincé pour vider la pile de navigation. après avoir déménagé dans un nouveau fragment.

Exemple: Je suis dans le loginFragment et je souhaite que ce fragment soit effacé de la pile lorsque je navigue vers le fragment de base afin que l'utilisateur ne soit pas renvoyé au loginFragment lorsqu'il appuiera sur le bouton Précédent.

J'utilise un simple NavHostFragment.findNavController (Fragment) .navigate (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 le naviguer () , mais le bouton Précédent me renvoie toujours au 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);
50
Youssef El Behi

Tout d'abord, ajoutez les attributs app:popUpTo='your_nav_graph_id' et app:popUpToInclusive="true" à la balise d'action.

<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, accédez à la destination en utilisant l’action ci-dessus comme paramètre.

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

Voir le docs pour plus d'informations.

NOTE: Si vous naviguez à l'aide de la méthode navigate(@IdRes int resId), vous n'obtiendrez pas le résultat souhaité. Par conséquent, j'ai utilisé la méthode navigate(@NonNull NavDirections directions).

73
Subhojit Shaw

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

Cette méthode est obsolète. Utilisez setPopUpTo (int, boolean) avec l'identifiant du graphique de NavController et définissez inclusive avec true.

Ancienne réponse

Si vous ne voulez pas parcourir tout ce fuzz dans le code, vous pouvez simplement vérifier Clear Task dans Launch Options dans les propriétés de l'action.

Launch Options

Modifier: À partir de Android Studio 3.2 Bêta 5, la tâche vide n'est plus visible dans la fenêtre Options de lancement, mais vous pouvez toujours utiliser dans le code XML de navigation, dans la balise action , en ajoutant

app:clearTask="true"
11
Mel

J'ai enfin compris grâce à Comment désactiver UP dans Navigation pour certains fragments avec le nouveau composant Architecture de navigation?

Je devais spécifier .setClearTask (true) en tant que 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());

                    }

                }
            });
4
Youssef El Behi

Dans mon cas, j'avais besoin de tout supprimer à l'arrière de la pile avant d'ouvrir un nouveau fragment, donc j'ai 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'à atteindre le fragment spécifié dans mon cas, c'est le fragment d'origine, de sorte qu'elle supprime complètement toute la pile arrière, et lorsque l'utilisateur clique en arrière dans fragment_company, il ferme l'application.

3
Nour Ahmed

Je pense que votre question concerne spécifiquement comment utiliser Pop Behavior/Pop To/app: popUpTo (en xml)

Dans la documentation,
Pop up à une destination donnée avant de naviguer. Cela affiche toutes les destinations non correspondantes de la pile arrière jusqu'à ce que cette destination soit trouvée.

Exemple (application de recherche d'emploi simple)
mon start_screen_nav Le graphique est comme ceci:

startScreenFragment (start) -> loginFragment -> EmployerMainFragment

                            -> loginFragment -> JobSeekerMainFragment

si je veux naviguer vers EmployerMainFragment et tout afficher comprenant startScreenFragment alors 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 vers EmployerMainFragment et tout afficher à l'exclusion startScreenFragment alors le code sera:

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

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

si je veux naviguer vers EmployerMainFragment et pop loginFragment mais ne pas startScreenFragment alors le code sera:

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

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

OR

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

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

Vous pouvez remplacer le fond de l'activité de base comme suit:

override fun onBackPressed() {

  val navigationController = nav_Host_fragment.findNavController()
  if (navigationController.currentDestination?.id == R.id.firstFragment) {
    finish()
  } else if (navigationController.currentDestination?.id == R.id.secondFragment) {
    // do nothing
  } else {
    super.onBackPressed()
  }

}
0
ROHIT LIEN