web-dev-qa-db-fra.com

Comment modifier la destination de départ d'un graphe de navigation par programme [Jetpack]

En gros, j'ai le graphe de navigation suivant:

enter image description here

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?

28
Shynline

UPDATE:

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.


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 sur votre code:

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

Ancienne réponse

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);
31
Alexey Denysenko

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:

  • Le fragment n ° 1 est l'endroit où ma demande commence initialement
  • Je peux effectuer une vérification d’authentification dans le fragment n ° 1, puis modifier par programme le début en fragment n ° 2.
  • Une fois dans le fragment 2, il n'y a plus de flèche vers le haut et appuyer sur le bouton Précédent ne vous conduit pas au fragment 1.

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.

1
szaske