94 votes

Comment modifier la destination de départ d'un graphique de navigation par programmation [Jetpack]

En gros, j'ai de navigation suivantes graphique:

enter image description here

Je veux changer mon point de départ dans la navigation graphique pour fragment 2 juste après l'atteindre (afin d'éviter de retourner à l' fragment 1 lorsque vous appuyez sur les bouton de retour avec l'écran de démarrage).

C'est mon code:

navGraph = navController.getGraph();
navGraph.setStartDestination(R.id.fragment2);
navController.setGraph(navGraph);

Mais, évidemment, ça ne marche pas et il sera de retour à l' fragment 1 après avoir appuyé sur bouton de retour.

Suis-je le fais mal? Est-il une autre solution?

93voto

Alexey Denysenko Points 2170

Mise à JOUR:

Lorsque vous avez nav graphique 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 souhaitez naviguer dans le deuxième fragment et de la rendre racine de votre graphique, préciser la prochaine NavOptions:

NavOptions navOptions = new NavOptions.Builder()
        .setPopUpTo(R.id.firstFragment, true)
        .build();

Et de les utiliser pour la navigation:

Navigation.findNavController(view).navigate(R.id.action_firstFragment_to_secondFragment, bundle, navOptions);

setPopUpTo(int destinationId, boolean inclusive) - 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.

destinationId - La destination de pop-up à, la compensation de tous les intervenant destinations.

inclusive - vrai également pop de la destination donnée à partir de la pile de retour.


ALTERNATIVE:

<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, dans votre code:

findNavController(fragment).navigate(
    FirstFragmentDirections.actionFirstFragmentToSecondFragment())

Vieille réponse

Obsolète: L' clearTask d'attribut pour les actions et les associés de l'API en NavOptions a été supprimée.

Source: https://developer.android.com/jetpack/docs/release-notes


Si vous souhaitez modifier votre fragment de racine de fragment 2 (par exemple, après avoir appuyé sur bouton de retour sur fragment 2 vous allez quitter l'application), vous devez mettre l'attribut suivant à votre action ou destination:

app:clearTask="true"

Pratiquement, il semble dans un façon suivante:

<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 effectuez la navigation à partir d' fragment 1 de fragment 2 utiliser le code suivant:

Navigation.findNavController(view)
        .navigate(R.id.action_firstFragment_to_secondFragment);

21voto

szaske Points 194

J'ai trouvé une solution pour cela, mais c'est moche. Je suppose que ce qu'il devrait être avec un alpha de la bibliothèque, mais j'espère que Google se penche sur la simplification/fixation de ce que c'est d'un très populaire modèle de navigation.

Alexey est la solution n'a pas fonctionné pour moi. Mon problème est que j'ai des flèches vers le bas de l'affichage sur mon Actionbar en utilisant:

NavigationUI.setupActionBarWithNavController(this, navController)

Si je n'ai que Alexey suggère ci-dessus, mon nouveau départ fragment toujours eu une flèche pointant vers mon départ initial fragment. Si j'ai appuyé sur cette flèche vers le haut de mon application serait de tri de la redémarrer, la transition vers lui-même (le nouveau départ fragment)

Voici le code nécessaire pour obtenir ce que je voulais, c'était:

  • Fragment n ° 1 est où ma demande d'abord commence
  • Je peux faire un Auth vérifier dans le Fragment n ° 1, puis modifier par programme le début de fragment #2.
  • Une fois dans le Fragment n ° 2 il n'y a pas de flèche vers le haut et en appuyant sur le bouton retour ne vous prennent pas au Fragment n ° 1.

Voici le code qui accomplit ce. Dans mon Activité de 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 du onActivityCreated, par Alexey suggestion:

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 de la clé est: (activity as MainActivity).makeHomeStart() qui passe juste une méthode dans l'activité que les changements graphiques startDestination. J'ai pu nettoyer cette et de le transformer en une interface, mais je vais attendre que Google et nous espérons qu'ils améliorent l'ensemble de ce processus. La méthode 'setPopUpTo" semble mal nommée à moi et ce n'est pas des plus intuitives que votre manière de nommer le fragment, c'est se couper de la graphique. C'est aussi étrange pour moi qu'ils font de ces changements dans navOptions. Je pense que navOptions serait seulement se rapportent à l'action de navigation ils sont connectés.

Et je ne sais même pas ce qu' navHost.navController.graph = graph , mais sans les flèches vers le haut retour. :(

Je suis l'aide de la Navigation 1.0.0-alpha06.

15voto

Kenny Points 460

Vous pouvez également essayer les éléments suivants.

 val navController = findNavController(R.id.nav_host_fragment)
if (condition) {
    navController.setGraph(R.navigation.nav_graph_first)
} else {
    navController.setGraph(R.navigation.nav_graph_second)
}
 

Au lieu d'essayer de sauter la destination de départ ou de naviguer manuellement vers la destination cible, il serait préférable d'avoir un autre graphique de navigation avec un flux de travail différent. Ce serait encore mieux dans le cas où vous souhaitez conditionnellement un flux de navigation complètement différent.

4voto

Pablo Valdes Points 16

Vous n'avez pas vraiment besoin de la pop le Splash Fragment. Elle peut y rester pour le reste de votre Application vie. Ce que vous devez faire est de partir de l'Écran de démarrage de déterminer le côté de l'Écran à Afficher.

Login State Machine flow

Dans l'image ci-dessus, vous pouvez demander à l'Écran de démarrage de l'État, si il est enregistré LoginToken. Dans le cas où est vide alors que vous accédez à l'Écran de Connexion.

Une fois l'Écran de Connexion est fait, alors vous analyser le résultat, enregistrez le Jeton et naviguez jusqu'à votre Prochain Fragment de l'Écran d'Accueil.

Lorsque le Bouton de Retour est Enfoncée dans l'Écran d'Accueil, vous permettra d'envoyer un message de Résultat à l'Écran de démarrage qui indique la fin de l'Application.

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