En gros, j'ai le graphe de navigation suivant:
Je souhaite modifier mon point de départ dans le graphique de navigation en fragment 2
juste après l’avoir atteint (pour éviter de revenir à fragment 1
lorsque vous appuyez sur le bouton Précédent - comme avec l’écran de démarrage).
Ceci est mon code:
navGraph = navController.getGraph();
navGraph.setStartDestination(R.id.fragment2);
navController.setGraph(navGraph);
Mais, évidemment, ça ne marche pas et ça retourne à fragment 1
après avoir appuyé sur le bouton Retour.
Est-ce que je me trompe? N 'y a-t-il pas une autre solution?
Lorsque vous avez un graphique de navigation comme ceci:
<fragment
Android:id="@+id/firstFragment"
Android:name="com.appname.package.FirstFragment" >
<action
Android:id="@+id/action_firstFragment_to_secondFragment"
app:destination="@id/secondFragment" />
</fragment>
<fragment
Android:id="@+id/secondFragment"
Android:name="com.appname.package.SecondFragment"/>
Et vous voulez naviguer vers le deuxième fragment et le placer en tant que racine de votre graphique, spécifiez le prochain NavOptions
:
NavOptions navOptions = new NavOptions.Builder()
.setPopUpTo(R.id.firstFragment, true)
.build();
Et utilisez-les pour la navigation:
Navigation.findNavController(view).navigate(R.id.action_firstFragment_to_secondFragment, bundle, navOptions);
setPopUpTo(int destinationId, boolean inclusive)
- Affiche 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.
destinationId
- La destination à afficher, en effaçant toutes les destinations intermédiaires.
inclusive
- true pour extraire également la destination donnée de la pile arrière.
<fragment
Android:id="@+id/firstFragment"
Android:name="com.appname.package.FirstFragment" >
<action
Android:id="@+id/action_firstFragment_to_secondFragment"
app:destination="@id/secondFragment"
app:popUpTo="@+id/firstFragment"
app:popUpToInclusive="true" />
</fragment>
<fragment
Android:id="@+id/secondFragment"
Android:name="com.appname.package.SecondFragment"/>
Et puis sur votre code:
findNavController(fragment).navigate(
FirstFragmentDirections.actionFirstFragmentToSecondFragment())
Déconseillé : L'attribut clearTask
pour les actions et l'API associée dans NavOptions
est obsolète.
Source: https://developer.Android.com/jetpack/docs/release-notes
Si vous voulez changer votre fragment racine en fragment 2
(Par exemple, après avoir appuyé sur le bouton Précédent de fragment 2
, Vous quitterez l'application), vous devez attribuer l'attribut suivant à votre action
ou destination
:
app:clearTask="true"
En pratique, cela ressemble à une autre manière:
<fragment
Android:id="@+id/firstFragment"
Android:name="com.appname.package.FirstFragment"
Android:label="fragment_first" >
<action
Android:id="@+id/action_firstFragment_to_secondFragment"
app:destination="@id/secondFragment"
app:clearTask="true" />
</fragment>
<fragment
Android:id="@+id/secondFragment"
Android:name="com.appname.package.SecondFragment"
Android:label="fragment_second"/>
J'ai ajouté app:clearTask="true"
À l'action.
Maintenant, lorsque vous naviguez de fragment 1
À fragment 2
, Utilisez le code suivant:
Navigation.findNavController(view)
.navigate(R.id.action_firstFragment_to_secondFragment);
J'ai trouvé une solution à cela, mais c'est moche. J'imagine que c'est ce à quoi il faut s'attendre avec une bibliothèque alpha, mais j'espère que Google cherchera à simplifier/corriger ce problème, car il s'agit d'un modèle de navigation très populaire.
La solution d'Alexey n'a pas fonctionné pour moi. Mon problème était que j'ai des flèches apparaissant sur ma barre d'actions en utilisant:
NavigationUI.setupActionBarWithNavController(this, navController)
Si j'ai agi comme Alexey le suggère ci-dessus, mon nouveau fragment de départ avait toujours une flèche pointant vers mon fragment de départ. Si j'appuyais sur cette flèche vers le haut, mon application serait en quelque sorte relancée, en passant à elle-même (le nouveau fragment de départ)
Voici le code nécessaire pour arriver à ce que je voulais qui était:
Voici le code qui accomplit ceci. Dans mon activité onCreate:
// Setup the toolbar
val toolbar = findViewById<Toolbar>(R.id.toolbar)
setSupportActionBar(toolbar)
supportActionBar?.setDisplayHomeAsUpEnabled(false)
// Configure the navigation
val navHost = nav_Host_fragment as NavHostFragment
graph = navHost.navController
.navInflater.inflate(R.navigation.nav_graph)
graph.startDestination = R.id.welcomeFragment
// This seems to be a magical command. Not sure why it's needed :(
navHost.navController.graph = graph
NavigationUI.setupActionBarWithNavController(this, navHost.navController)
et aussi:
fun makeHomeStart(){
graph.startDestination = R.id.homeFragment
}
Ensuite, dans le fragment n ° 1 de onActivityCreated, selon la suggestion d'Alexey:
override fun onActivityCreated(savedInstanceState: Bundle?) {
...
// Check for user authentication
if(sharedViewModel.isUserAuthenticated()) {
(activity as MainActivity).makeHomeStart() //<---- THIS is the key
val navOptions = NavOptions.Builder()
.setPopUpTo(R.id.welcomeFragment, true)
.build()
navController.navigate(R.id.action_welcomeFragment_to_homeFragment,null,navOptions)
} else {
navController.navigate(R.id.action_welcomeFragment_to_loginFragment)
}
}
Le code clé est: (activity as MainActivity).makeHomeStart()
qui exécute simplement une méthode dans l'activité qui modifie les graphes startDestination. Je pourrais nettoyer cela et en faire une interface, mais j'attendrai Google et j'espère qu'ils amélioreront tout ce processus. La méthode 'setPopUpTo' me semble mal nommée et ce n'est pas intuitif que vous nommiez le fragment qui est coupé du graphique. Il est également étrange pour moi qu'ils apportent ces modifications dans navOptions. Je pense que navOptions ne concerne que l’action de navigation à laquelle ils sont connectés.
Et je ne sais même pas quoi navHost.navController.graph = graph
fait, mais sans elle les flèches vers le haut reviennent. :(
J'utilise Navigation 1.0.0-alpha06.