Search code examples
androidandroid-jetpackandroid-navigationandroid-architecture-navigation

How to change start destination of a navigation graph programmatically?


Basically, I have the following navigation graph:

enter image description here

I want to change my starting point in navigation graph to fragment 2 right after reaching it (in order to prevent going back to fragment 1 when pressing back button - like with the splash screen).

This is my code:

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

But, obviously it's not working and it gets back to fragment 1 after pressing back button.

Am I doing it wrong? Is there any other solution?


Solution

  • UPDATE:

    When you have nav graph like this:

    <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"/>
    

    And you want to navigate to the second fragment and make it root of your graph, specify the next NavOptions:

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

    And use them for the navigation:

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

    setPopUpTo(int destinationId, boolean inclusive) - Pop up to a given destination before navigating. This pops all non-matching destinations from the back stack until this destination is found.

    destinationId - The destination to pop up to, clearing all intervening destinations.

    inclusive - true to also pop the given destination from the back stack.


    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"/>
    

    And then on your code:

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

    Old answer

    Deprecated: The clearTask attribute for actions and the associated API in NavOptions has been deprecated.

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


    If you want to change your root fragment to fragment 2 (e.g. after pressing back button on fragment 2 you will exit the app), you should put the next attribute to your action or destination:

    app:clearTask="true"
    

    Practically it looks in a next way:

    <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"/>
    

    I've added app:clearTask="true" to action.


    Now when you perform navigation from fragment 1 to fragment 2 use the next code:

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