The interactions that allow users to travel through, into, and out of the various pieces of content within your app are referred to as navigation. The component of Android Jetpack navigation assists you in implementing navigation.
Jetpack Navigation depends on –
The Jetpack Navigation component depends on the below-mentioned parts:
Navigation Graph: A navigation graph is an XML resource that contains all navigation-related information in one place. This includes all of your app’s individual content areas, known as destinations, as well as the various paths a user can take through your app.
NavHost: A container that is empty and displays destinations from your navigation graph. The Navigation component includes a NavHost implementation by default, NavHostFragment, which displays fragment destinations.
NavController: A NavHost object that manages app navigation. As users move through your app, the NavController orchestrates the swapping of destination content in the NavHost.
As you navigate through your app, you tell the NavController
that you want to navigate either along a specific path in your navigation graph or directly to a specific destination. The NavController
then shows the appropriate destination in the NavHost
.
Advantages
The Navigation part gives various different advantages, including the mentioned below:
- Handling fragment transactions.
- Handling Up and Back actions correctly by default.
- Providing standardized resources for animations and transitions.
- Implementing and handling deep linking.
- Including Navigation UI patterns, such as navigation drawers and bottom navigation, with minimal additional work.
- Safe Args – a Gradle plugin that provides type safety when navigating and passing data between destinations.
Start the implementation
Step-1 Add the dependencies
In your build.gradle (module-level) file
1 2 3 |
def nav_version = "2.4.2" implementation("androidx.navigation:navigation-fragment-ktx:$nav_version") implementation("androidx.navigation:navigation-ui-ktx:$nav_version") |
In your build.gradle (app level) file OPTIONAL for safe_args
1 |
classpath("androidx.navigation:navigation-safe-args-gradle-plugin:2.4.2") |
Also, add a plugin in your module-level build.gradle file for safe args
1 |
id("androidx.navigation.safeargs.kotlin") |
Step -2 Create a resource file
To add a navigation graph to your project, do the following:
- In the Project window, right-click on the
res
directory and select New > Android Resource File. The New Resource File dialog appears. - Type a name in the File name field, such as “nav_graph”.
- Select Navigation from the Resource type drop-down list, and then click OK.
When you add your first navigation graph, Android Studio creates a navigation
resource directory within the res
directory. This directory contains your navigation graph resource file (nav_graph.xml
, for example).
for reference, check this screenshot
Step-3 Add Frgmant Container View
From the below code we will add a NavHostFragment
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
<?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"> <androidx.fragment.app.FragmentContainerView android:id="@+id/nav_host_fragment" android:name="androidx.navigation.fragment.NavHostFragment" android:layout_width="0dp" android:layout_height="0dp" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toBottomOf="parent" app:defaultNavHost="true" app:navGraph="@navigation/nav_graph" /> </androidx.constraintlayout.widget.ConstraintLayout> |
Step-4 Let’s start work on your navigation graph
For the demo, we have added 2 fragments Fragment A and Fragment B
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
<?xml version="1.0" encoding="utf-8"?> <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/nav_graph" app:startDestination="@id/fragmentA"> <fragment android:id="@+id/fragmentA" android:name="com.example.androidnavigation.FragmentA" android:label="fragment_a" tools:layout="@layout/fragment_a"> <action android:id="@+id/pass_string" app:destination="@id/fragmentB"> <argument android:name="stringDemo" android:defaultValue="EMPTY" app:argType="string" app:nullable="true" /> </action> <action android:id="@+id/pass_user" app:destination="@id/fragmentB"> <argument android:name="userData" app:argType="com.example.androidnavigation.UserData" app:nullable="true" /> </action> <action android:id="@+id/pass_both" app:destination="@id/fragmentB"> <argument android:name="userData" app:argType="com.example.androidnavigation.UserData" app:nullable="true" /> </action> </fragment> <fragment android:id="@+id/fragmentB" android:name="com.example.androidnavigation.FragmentB" android:label="fragment_b" tools:layout="@layout/fragment_b"> <argument android:name="stringDemo" android:defaultValue="EMPTY" app:nullable="true" app:argType="string" /> <argument android:name="userData" app:nullable="true" android:defaultValue="@null" app:argType="com.example.androidnavigation.UserData" /> </fragment> </navigation> |
Here you can check that we have added some action from fragment A to Frgament B with argumnets
Step-5 Now it’s time to navigate
Here, is our Fragment A
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
class FragmentA : Fragment() { override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { // Inflate the layout for this fragment return inflater.inflate(R.layout.fragment_a, container, false) } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) val btn1 = view.findViewById<MaterialButton>(R.id.button1) val btn2 = view.findViewById<MaterialButton>(R.id.button2) val btn3 = view.findViewById<MaterialButton>(R.id.button3) btn1.setOnClickListener { findNavController().navigate(FragmentADirections.passString("Hello Arguments Received")) } btn2.setOnClickListener { findNavController().navigate(FragmentADirections.passUser(UserData())) } btn3.setOnClickListener { findNavController().navigate( FragmentADirections.passBoth( UserData(), "Arguments Received" ) ) } } } |
As a result, we move to fragment B with the passed arguments.
Here, is our Fragmet B
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
class FragmentB : Fragment() { val args: FragmentBArgs by navArgs() override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { // Inflate the layout for this fragment return inflater.inflate(R.layout.fragment_b, container, false) } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) val argsText = view.findViewById<TextView>(R.id.stringText) val userText = view.findViewById<TextView>(R.id.userText) argsText.text = args.stringDemo if (args.userData != null) userText.text = "${args.userData?.userId}\n${args.userData?.userName}\n${args.userData?.userEmail}" } } |
Here is our UserData data class
1 2 3 |
import java.io.Serializable data class UserData(var userName: String = "Demo", val userId: String = "1", var userEmail: String = "demo@email.com"):Serializable |
Note:- Please make your data class Serializable or Parcelable if you want to pass this as an argument
In the above example, you can see that we are passing some data from Fragment A to Fragment B
From btn1:- We are just passing a string value
For results check this screenshot
From btn2:- We are just passing User Details with a null string
For results check this screenshot
Note: Here you can see that “EMPTY” is visible for the string argument which we have passed as a default value in our navigation graph.
From btn3:- We are passing both string and User Details with this action
For results check this screenshot
For more details, please check this link
Hopefully, this blog will be helpful to you. If you have any queries, please write them in the comment section.