Android Jetpack Navigation Example

This post is about Android Jetpack Navigation and how to set up and work with the Navigation component.

 

Jetpack Navigation

Navigation refers to the interactions that allow users to navigate across, into, and back out from the different pieces of content within your app.

Android Jetpack’s Navigation component helps you implement navigation, from simple button clicks to more complex patterns, such as app bars and the navigation drawer.

The Navigation component consists of three key parts that are described below:

NavHost:

The navigation host is an empty container where destinations are swapped in and out as a user navigates through your app. The Navigation component contains a default NavHost implementation, NavHostFragment, that displays fragment destinations.

Navigation graph:

An XML resource that contains all navigation-related information in one centralized location. This includes all of the individual content areas within your app, called destinations, as well as the possible paths that a user can take through your app.

NavController:

An object that manages app navigation within a NavHost. The NavController orchestrates the swapping of destination content in the NavHost as users move throughout your app.

Creating new project

1 . Create a new project by going to File ⇒ New Android Project, select Empty Activity, provide app name, select language to kotlin and then finally click on finish.

2 . Open app-level build.gradle file and add the below libraries under the dependencies section:

build.gradle

dependencies {
// jetpack navigation dependency for kotlin
implementation("androidx.navigation:navigation-fragment-ktx:2.4.1")
implementation("androidx.navigation:navigation-ui-ktx:2.4.1")
}

Note: Update the navigation library with the latest version from here.

3. The below XML file shows a NavHostFragment as part of an app’s main activity:

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

<fragment
android:id="@+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:navGraph="@navigation/nav_graph" />

</androidx.constraintlayout.widget.ConstraintLayout>
  • android:name: attribute contains the class name of your NavHost implementation.
  • app:navGraph: defines which Navigation Graph will be associated with the Navigation Host.
  • app:defaultNavHost=”true”: ensures that the Navigation Host intercepts the system back button when pressed.

Creating Fragments

4. Let’s create two Fragments i.e. FragmentA and FragmentB.

Creating Fragment’s kotlin file

FragmentA.kt

package com.c1ctech.jetpacknavigation

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import androidx.fragment.app.Fragment
import androidx.navigation.findNavController

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)

//get NavController instance
val navController = view.findNavController()

val button = view.findViewById<Button>(R.id.btnGotoFragmentB)

button.setOnClickListener {
//navigates from fragment A to Fragment B
navController.navigate(R.id.action_fragmentA_to_fragmentB) }
}
}

FragmentB.kt

package com.c1ctech.jetpacknavigation

import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup

class FragmentB : Fragment() {

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)
}
}
Creating Fragment’s layout file

fragment_a.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".FragmentA">

<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:text="FragmentA"
android:textSize="30sp" />

<Button
android:id="@+id/btnGotoFragmentB"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal|bottom"
android:text="Goto FragmentB"
android:textAllCaps="false" />

</FrameLayout>

fragment_b.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".FragmentB">

<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:text="FragmentB"
android:textSize="30sp" />

</FrameLayout>

5. Right-click on the res directory and choose New -> Android resource file. Set the title for the file and choose Navigation from the Resource type dropdown and then click on ok.

nav_graph.xml

<?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.c1ctech.jetpacknavigation.FragmentA"
android:label="FragmentA"
tools:layout="@layout/fragment_a">

<action
android:id="@+id/action_fragmentA_to_fragmentB"
app:destination="@id/fragmentB" />

</fragment>

<fragment
android:id="@+id/fragmentB"
android:name="com.c1ctech.jetpacknavigation.FragmentB"
android:label="FragmentB"
tools:layout="@layout/fragment_b"/>

</navigation>
  • app:startDestination: defines the starting destination. 
  • android:name: shows the name of the fragment that is associated with the destination.
  • android:label: contains the user-readable name of the destination.
  • tools:layout: defines the layout of the destination.
  • action: defines the destination to which the user navigates using destination attribute.

Writing MainActivity Code

6. The MainActivity file contains the below code:

MainActivity.kt

package com.c1ctech.jetpacknavigation

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.navigation.NavController
import androidx.navigation.findNavController
import androidx.navigation.ui.NavigationUI.setupActionBarWithNavController

class MainActivity : AppCompatActivity() {

lateinit var navController: NavController

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)

navController = this.findNavController(R.id.nav_host_fragment)

setupActionBarWithNavController(this, navController)
}

override fun onSupportNavigateUp(): Boolean {
navController.navigateUp()
return super.onSupportNavigateUp()
}
}

In the above code,

  • this.findNavController() gives us the instance of NavController.
  • setupActionBarWithNavController(): Sets up the ActionBar returned by AppCompatActivity.getSupportActionBar for use with a NavController.By calling this method, the title in the action bar will automatically be updated when the destination changes.
  • onSupportNavigateUp(): This method is called whenever the user chooses to navigate Up within your application’s activity hierarchy from the action bar.

When you run the app it will look like this:

           

 

Leave a Reply