Kotlin Android Jetpack Navigation Component Example

Step by Step Kotlin Android Jetpack Navigation Tutorial and Example

In this piece you will learn about Navigation Component through step by step android examples in Kotlin.

But first what is 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 also ensures a consistent and predictable user experience by adhering to an established set of principles.

Here is a video explanation:


Parts of a Navigation Component

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

  • 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.
  • NavHost: An empty container that displays destinations from your navigation graph. The Navigation component contains a default NavHost implementation, NavHostFragment, that displays fragment destinations.
  • 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.

Advantages of using a Navigation Component

The Navigation Component provides several advantages over traditional navigation pattersm. These include:

  • It handles fragment transactions for you.
  • It handles Up and Back actions for you.
  • It provides standardized resources for animations and transitions.
  • It provides Implementation and handling of deep linking.
  • Through it you can Include 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.
  • ViewModel support – you can scope a ViewModel to a navigation graph to share UI-related data between the graph’s destinations.

Step 1: Dependencies

Add the following Navigation Component dependencies in your gradle file:

    // Kotlin
    implementation "androidx.navigation:navigation-fragment-ktx:$nav_version"
    implementation "androidx.navigation:navigation-ui-ktx:$nav_version"

    // Feature module Support
    implementation "androidx.navigation:navigation-dynamic-features-fragment:$nav_version"

Step 2: Create a Navigation Graph

The Navigation Graph as we had said is simply an XML resource that will contain all the navigation related information in one place. To create it, start by creating a folder known as navigation in your res directory. Then in this folder create a file called simple_navigation.xml and add the following code:

simple_navigation.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/simple_navigation"
    app:startDestination="@id/homeFragment">

    <fragment
        android:id="@+id/homeFragment"
        android:name="com.example.mvvmnavigation.view.fragment.HomeFragment"
        android:label="fragment_home"
        tools:layout="@layout/fragment_home" >
        <action
            android:id="@+id/action_homeFragment_to_searchFragment"
            app:destination="@id/searchFragment"
            app:enterAnim="@anim/nav_default_pop_enter_anim"
            app:exitAnim="@anim/nav_default_pop_exit_anim" />
    </fragment>
    <fragment
        android:id="@+id/searchFragment"
        android:name="com.example.mvvmnavigation.view.fragment.SearchFragment"
        android:label="fragment_search"
        tools:layout="@layout/fragment_search" >
        <action
            android:id="@+id/action_searchFragment_to_homeFragment"
            app:destination="@id/homeFragment" />
        <action
            android:id="@+id/action_searchFragment_to_responsFragment"
            app:destination="@id/responsFragment"
            app:enterAnim="@anim/nav_default_pop_enter_anim"
            app:exitAnim="@anim/nav_default_pop_exit_anim" />
    </fragment>
    <fragment
        android:id="@+id/responsFragment"
        android:name="com.example.mvvmnavigation.view.fragment.ResponsFragment"
        android:label="fragment_respons"
        tools:layout="@layout/fragment_respons" >
        <action
            android:id="@+id/action_responsFragment_to_searchFragment"
            app:destination="@id/searchFragment" />
    </fragment>
</navigation>

Step 3: Create Fragment Layouts

In your layouts folder, create the XML UI designs for the Navigation Destinations. In this case we will have three fragments:

fragment_search.xml

In this fragment add three widgets: a TextView, a Button and a MultiAutoCompleteTextView:

<?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=".view.fragment.SearchFragment">

    <MultiAutoCompleteTextView
        android:id="@+id/multiAutoCompleteTextView_searchFragment_Search"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="Search"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/textView_searchFragment_listSearch"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="10dp"
        android:background="#FFFFFF"
        android:elevation="6dp"
        android:gravity="center"
        android:padding="5dp"
        android:text="@string/str_list_search"
        app:layout_constraintBottom_toTopOf="@+id/btn_searchFragment_Search"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/multiAutoCompleteTextView_searchFragment_Search" />

    <Button
        android:id="@+id/btn_searchFragment_Search"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="104dp"
        android:text="Search"
        android:textAllCaps="false"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="@+id/multiAutoCompleteTextView_searchFragment_Search"
        app:layout_constraintVertical_bias="0.987" />
</androidx.constraintlayout.widget.ConstraintLayout>

fragment_respons.xml

Add two textview here:

<?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=".view.fragment.ResponsFragment"
    android:padding="10dp">

    <TextView
        android:id="@+id/textView_ResponsFragment_AboutMe"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/str_about_me"
        android:padding="10dp"
        android:layout_margin="10dp"
        android:layout_marginLeft="10dp"
        android:layout_marginRight="10dp"
        android:background="#FFFFFF"
        android:elevation="6dp"
        android:gravity="center"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/textView_ResponsFragment_Respons"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text=""
        android:padding="10dp"
        android:layout_margin="10dp"
        android:background="#FFFFFF"
        android:elevation="6dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/textView_ResponsFragment_AboutMe" />

</androidx.constraintlayout.widget.ConstraintLayout>

fragment_home.xml

Add a button here:

<?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=".view.fragment.HomeFragment">

    <Button
        android:id="@+id/btn_homeFragment_search"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Go To Search"
        android:textAllCaps="false"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

Step 4: Create Fragments

In this step you will write the code for the individual fragments. There are three fragments:

(a). SearchFragment.kt

Create the fragment by extending the Fragment class. Initialize the Button and MultiAutoCompleteTextView. The MultiAutoCompleteTextView will be used to search/filter the list. The search result will be transfered to the ResponsFragment via a Bundle object.

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ArrayAdapter
import android.widget.Button
import android.widget.MultiAutoCompleteTextView
import androidx.fragment.app.Fragment
import androidx.navigation.Navigation
import com.example.mvvmnavigation.R

class SearchFragment : Fragment() {

    lateinit var btn_search: Button
    lateinit var autoTextView: MultiAutoCompleteTextView

    override fun onCreateView(
            inflater: LayoutInflater, container: ViewGroup?,
            savedInstanceState: Bundle?
    ): View? {
        // Inflate the layout for this fragment
        val view = inflater.inflate(R.layout.fragment_search, container, false)

        Cast(view)

        return view
    }

    private fun Cast(view: View) {

        autoTextView = view.findViewById(R.id.multiAutoCompleteTextView_searchFragment_Search)
        btn_search = view.findViewById(R.id.btn_searchFragment_Search)

        val dataSearch = listOf(
                "ali",
                "reza",
                "mvvm",
                "nav",
                "android",
                "alireza",
                "mmd",
                "mvp",
                "kotlin",
                "java",
                "python",
                "telegram",
                "api",
                "android 10",
                "android 11",
                "android studio"
                )

        autoTextView.setAdapter(ArrayAdapter(view.context,android.R.layout.simple_list_item_1,dataSearch))
        autoTextView.threshold = 1
        autoTextView.setTokenizer(MultiAutoCompleteTextView.CommaTokenizer())

    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        btn_search.setOnClickListener {

            val data = Bundle()
            data.putString("data", autoTextView.text.toString())
            Navigation.findNavController(btn_search).navigate(R.id.action_searchFragment_to_responsFragment,data)

        }
    }

}

(b). ResponsFragment.kt

Here you inflate the fragment_respons.xml layout then initialize the textview defined in it. This textview will be showing the search results. You receive these search results from the Search Fragment.

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.fragment.app.Fragment
import com.example.mvvmnavigation.R

class ResponsFragment : Fragment() {

    lateinit var txt: TextView

    override fun onCreateView(
            inflater: LayoutInflater, container: ViewGroup?,
            savedInstanceState: Bundle?
    ): View? {
        // Inflate the layout for this fragment
        val view = inflater.inflate(R.layout.fragment_respons, container, false)

        Cast(view)

        return view
    }

    private fun Cast(view: View) {
        txt = view.findViewById(R.id.textView_ResponsFragment_Respons)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        val data: String? = arguments?.getString("data")

        if (data?.length ?: 0 >= 1)
            txt.text = data
        else
            txt.text = "Null"

    }

}

(a). HomeFragment.kt

From this home fragment you will navigate over to the SearchFragment. From there you will navigate over to the ResponseFragment. This fragment contains a button that when clicked initiates that navigation:

import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import androidx.navigation.Navigation
import com.example.mvvmnavigation.R

class HomeFragment : Fragment() {

    lateinit var btn_go_to_search : Button

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        // Inflate the layout for this fragment
        val view = inflater.inflate(R.layout.fragment_home, container, false)

        Cast(view)

        return view
    }

    private fun Cast(view: View){

        btn_go_to_search = view.findViewById(R.id.btn_homeFragment_search)

    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        btn_go_to_search.setOnClickListener {

            val navDirections = HomeFragmentDirections.actionHomeFragmentToSearchFragment()
            Navigation.findNavController(btn_go_to_search).navigate(navDirections)

        }

    }

}

Step 5: Create Main Activity

Fragments need to be hosted in an activity. For us this will be the MainActivity, our launcher activity. Here we will attach the NavigationController to the NavHost. Here is the full code:

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.databinding.DataBindingUtil
import androidx.navigation.NavController
import androidx.navigation.Navigation
import androidx.navigation.ui.NavigationUI
import com.example.mvvmnavigation.R
import com.example.mvvmnavigation.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity() {

    private lateinit var binding: ActivityMainBinding
    lateinit var navController: NavController

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = DataBindingUtil.setContentView(this, R.layout.activity_main)

        navController = Navigation.findNavController(this, R.id.fragment)
        NavigationUI.setupActionBarWithNavController(this, navController)

    }
}

Run

Finally run the project.

Reference

Here are the reference links:

Number Link
1. Download code
2. Follow code author
3. Navigation Component Reference

BEFORE YOU GO

YOU'VE BEEN SELECTED FOR A GIFT

Thanks for stopping by. My name is Oclemy(Clement Ochieng) and we have selected you as a recipient of a GIFT you may like ! Together with Skillshare we are offering you PROJECTS and 1000s of PREMIUM COURSES at Skillshare for FREE for 1 MONTH. To be eligible all you need is by sign up right now using my profile .

Leave a Reply

Your email address will not be published. Required fields are marked *

*

code