Is it possible to set startDestination conditionally using Android Navigation Architecture Component(Android Jetpack)? Is it possible to set startDestination conditionally using Android Navigation Architecture Component(Android Jetpack)? android android

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)}