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