Is it possible to set startDestination conditionally using Android Navigation Architecture Component(Android Jetpack)?
Finally, I got a solution to my query...
Put below code in onCreate()
method of Activity
.
Kotlin code
val navHostFragment = (supportFragmentManager.findFragmentById(R.id.home_nav_fragment) as NavHostFragment)val inflater = navHostFragment.navController.navInflaterval graph = inflater.inflate(R.navigation.nav_main)//graph.addArgument("argument", NavArgument)graph.startDestination = R.id.fragment1//or//graph.startDestination = R.id.fragment2navHostFragment.navController.graph = graph
Java code
NavHostFragment navHostFragment = (NavHostFragment) getSupportFragmentManager().findFragmentById(R.id.home_nav_fragment); // HostfragmentNavInflater inflater = navHostFragment.getNavController().getNavInflater();NavGraph graph = inflater.inflate(R.navigation.nav_main);//graph.addArgument("argument", NavArgument)graph.setStartDestination(R.id.fragment1);navHostFragment.getNavController().setGraph(graph);navHostFragment.getNavController().getGraph().setDefaultArguments(getIntent().getExtras());NavigationView navigationView = findViewById(R.id.navigationView);NavigationUI.setupWithNavController(navigationView, navHostFragment.getNavController());
Additional Info
As @artnest suggested, remove the app:navGraph
attribute from the layout. It would look something like this after removal
<?xml version="1.0" encoding="utf-8"?><FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent"> <androidx.fragment.app.FragmentContainerView android:id="@+id/home_nav_fragment" android:name="androidx.navigation.fragment.NavHostFragment" android:layout_width="match_parent" android:layout_height="match_parent" app:defaultNavHost="true" /></FrameLayout>
In the case of a fragment
tag used instead of FragmentContainerView
, the above changes remain the same
Some of the APIs have changed, are unavailable or are not necessary since Akash's answer. It's a bit simpler now.
MainActivity.java
:
@Overrideprotected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); NavHostFragment navHost = (NavHostFragment) getSupportFragmentManager().findFragmentById(R.id.fragment_main_nav_host); NavController navController = navHost.getNavController(); NavInflater navInflater = navController.getNavInflater(); NavGraph graph = navInflater.inflate(R.navigation.navigation_main); if (false) { graph.setStartDestination(R.id.oneFragment); } else { graph.setStartDestination(R.id.twoFragment); } navController.setGraph(graph);}
activity_main.xml
:
<?xml version="1.0" encoding="utf-8"?><androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <!-- Following line omitted inside <fragment> --> <!-- app:navGraph="@navigation/navigation_main" --> <fragment android:id="@+id/fragment_main_nav_host" android:layout_width="match_parent" android:layout_height="match_parent" android:name="androidx.navigation.fragment.NavHostFragment" /></androidx.constraintlayout.widget.ConstraintLayout>
navigation_main.xml
:
<?xml version="1.0" encoding="utf-8"?><!-- Following line omitted inside <navigation>--><!-- app:startDestination="@id/oneFragment" --><navigation xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/navigation_main" > <fragment android:id="@+id/oneFragment" android:name="com.apponymous.apponymous.OneFragment" android:label="fragment_one" tools:layout="@layout/fragment_one"/> <fragment android:id="@+id/twoFragment" android:name="com.apponymous.apponymous.TwoFragment" android:label="fragment_two" tools:layout="@layout/fragment_two"/></navigation>
This can be done with navigation action. Because fragmentA is your start destination, so define an action in fragmentA.
Note these two fields: app:popUpToInclusive="true" app:popUpTo="@id/fragmentA"
<navigation xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/lrf_navigation" app:startDestination="@id/fragmentA"> <fragment android:id="@+id/fragmentA" android:name="com.mindinventory.FragmentA" android:label="fragment_a" tools:layout="@layout/fragment_a"> <action android:id="@+id/action_a_to_b" app:destination="@id/fragmentB" app:popUpToInclusive="true" app:popUpTo="@id/fragmentA"/> <fragment> <fragment android:id="@+id/fragmentB" android:name="com.mindinventory.FragmentB" android:label="fragment_b" tools:layout="@layout/fragment_b"/></navigation>
When your MainActivity started, just do the navigation with action id, it will remove fragmentA in the stack, and jump to fragmentB. Seemingly, fragmentB is your start destination.
if(!isAllSetUp){ // FragmentB navController.navigate(R.id.action_a_to_b)}