Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

I am using Navigation from Android Jetpack to navigate between screens. Now I want to set startDestination dynamically.

I have an Activity named MainActivity And two Fragments, FragmentA & FragmentB.

var isAllSetUp : Boolean = // It is dynamic and I’m getting this from Preferences.      If(isAllSetUp)     {      // show FragmentA     }     else     {      //show FragmentB     } 

I want to set above flow using Navigation Architecture Component. Currently I have used startDestionation as below but it’s not fulfilling my requirement.

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

Is it possible to set startDestination conditionally using Android Navigation Architecture Component?

like image 209
Akash Patel Avatar asked Aug 20 '18 10:08

Akash Patel


People also ask

What is navigation component in Android jetpack?

The navigation component is a component of the android jetpack that helps us to implement navigation from simple button click to very complex design patterns.

What programming language is used for navigation component in Android?

Nowadays mostly developers use the Kotlin language for mobile application development with android clean architecture and due to the architecture of android developers prefer advanced techniques of android like MVVM, ViewBinding, DataBinding, and Dependency Injection, and many more features of the jetpack so here Navigation Component one of them.

What is the best way to organize Android app navigation stack?

Android navigation stack should follow a LIFO structure. With the starting screen at bottom of the stack and the current on top. The up button should never exit your app. With the exception of the bottom element of the stack, the up button should function identically to the system back button.

What is Android jetpack and why should you care?

Google IO 2018 added new components and mixed them with the existing support libraries to create what they now call Android Jetpack — a set of categorised unbundled libraries that can be added according to your application’s needs.


2 Answers

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.navInflater val graph = inflater.inflate(R.navigation.nav_main) //graph.addArgument("argument", NavArgument) graph.startDestination = R.id.fragment1 //or //graph.startDestination = R.id.fragment2  navHostFragment.navController.graph = graph 

Java code

NavHostFragment navHostFragment = (NavHostFragment) getSupportFragmentManager().findFragmentById(R.id.home_nav_fragment);  // Hostfragment NavInflater 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

like image 106
Akash Patel Avatar answered Oct 14 '22 11:10

Akash Patel


Some of the APIs have changed, are unavailable or are not necessary since Akash's answer. It's a bit simpler now.

MainActivity.java:

@Override protected 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> 
like image 24
Danish Khan Avatar answered Oct 14 '22 11:10

Danish Khan