Android Navigation Component Jetpack in Kotlin
This post shows you how to implement the jetpack android navigation component using kotlin programming language in your android app.
Android navigation component helps developers to anticipate navigation flow of application. Android navigation component consists of three key parts that are described below. You can also checkout full source code at Github.
- 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.

Add the below dependencies in your app level build.gradle
apply plugin: 'kotlin-kapt' apply plugin: 'androidx.navigation.safeargs.kotlin' android { dataBinding{ enabled true } compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } kotlinOptions { jvmTarget = JavaVersion.VERSION_1_8.toString() } } dependencies { implementation 'androidx.navigation:navigation-fragment-ktx:2.2.1' implementation 'androidx.navigation:navigation-ui-ktx:2.2.1' implementation 'com.android.support:recyclerview-v7:28.1.1' implementation 'com.android.support:cardview-v7:28.1.1' }
Add the below dependency in your top level build.gradle
dependencies { classpath 'com.android.tools.build:gradle:3.6.1' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath 'android.arch.navigation:navigation-safe-args-gradle-plugin:1.0.0' }
Create a navigation graph for android navigation component
To add a navigation graph to your project, do the following:
1. In the Project window, right-click on the res directory and select New > Android Resource File. The New Resource File dialog appears.
2. Type a name in the File name field, such as “nav_graph”.
3. Select Navigation from the Resource type drop-down list, and then click OK.
Add a NavHost to an activity
<?xml version="1.0" encoding="utf-8"?> <layout 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"> <data> </data> <androidx.constraintlayout.widget.ConstraintLayout android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".activities.MainActivity"> <fragment android:id="@+id/nav_host_fragment" android:layout_width="0dp" android:layout_height="0dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" android:name="androidx.navigation.fragment.NavHostFragment" app:defaultNavHost="true" app:navGraph="@navigation/nav_graph"/> </androidx.constraintlayout.widget.ConstraintLayout> </layout>
Add destinations to the navigation graph
To add a new destination using the Navigation Editor, do the following:
1. In the Navigation Editor, click the New Destination icon , and then click Create new destination.
2. In the New Android Component dialog that appears, create your fragment.
Output will be
<?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/employeesListFragment"> <fragment android:id="@+id/employeesListFragment" android:name="com.example.navigationjetpacksample.fragments.EmployeesListFragment" android:label="EmployeesListFragment" tools:layout="@layout/frag_employees_list"/> </navigation>
Connect destinations for android navigation component
You can use the Navigation Editor to connect two destinations by doing the following:
1. In the Design tab, hover over the right side of the destination that you want users to navigate from. A circle appears over the right side of the destination
2. Click and drag your cursor over the destination you want users to navigate to, and release. The resulting line between the two destinations represents an action
Output will be
<?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/employeesListFragment"> <fragment android:id="@+id/employeesListFragment" android:name="com.example.navigationjetpacksample.fragments.EmployeesListFragment" android:label="EmployeesListFragment" tools:layout="@layout/frag_employees_list"> <action android:id="@+id/action_employeesListFragment_to_employeeDetailsFragment" app:destination="@id/employeeDetailsFragment" /> <action android:id="@+id/action_employeesListFragment_to_addEmployeeFragment" app:destination="@id/addEmployeeFragment" /> <action android:id="@+id/action_employeesListFragment_to_editEmployeeFragment" app:destination="@id/editEmployeeFragment" /> <action android:id="@+id/action_employeesListFragment_to_deleteEmployeeFragment" app:destination="@id/deleteEmployeeFragment" /> </fragment> </navigation>
Navigate to a destination
Kotlin:
- Fragment.findNavController()
- View.findNavController()
- Activity.findNavController(viewId: Int)
Java:
- NavHostFragment.findNavController(Fragment)
- Navigation.findNavController(Activity, @IdRes int viewId)
- Navigation.findNavController(View)
fab_add.setOnClickListener { it.findNavController().navigate(EmployeesListFragmentDirections.actionEmployeesListFragmentToAddEmployeeFragment()) }
Pass data between destinations with Safe Args
To pass data between destinations, first define the argument by adding it to the destination that receives it by following these steps:
1. In the Navigation editor, click on the destination that receives the argument.
2. In the Attributes panel, click Add (+).
3. In the Add Argument Link window that appears, enter the argument name, argument type, whether the argument is nullable, and a default value, if needed.
4. Click Add. Notice that the argument now appears in the Arguments list in the Attributes panel.
Output will be
<fragment android:id="@+id/employeeDetailsFragment" android:name="com.example.navigationjetpacksample.fragments.EmployeeDetailsFragment" android:label="EmployeeDetailsFragment" tools:layout="@layout/frag_employee_details"> <argument android:name="employee" app:argType="com.example.navigationjetpacksample.models.Employee" /> </fragment>
For optional arguments
<fragment android:id="@+id/employeeDetailsFragment" android:name="com.example.navigationjetpacksample.fragments.EmployeeDetailsFragment" android:label="EmployeeDetailsFragment" tools:layout="@layout/frag_employee_details"> <argument android:name="employee" app:argType="com.example.navigationjetpacksample.models.Employee" android:defaultValue="@null" app:nullable="true"/> </fragment>
package com.example.navigationjetpacksample.models import java.io.Serializable data class Employee(val id: Int, val firstName: String, val lastName: String, val email: String, val phoneNo:String, val age:String, val salary:String) : Serializable
In your sending destination’s code
holder.itemBinding.root.setOnClickListener { val action = EmployeesListFragmentDirections.actionEmployeesListFragmentToEmployeeDetailsFragment(getEmployee) it.findNavController().navigate(action) }
In your receiving destination’s code
val args : EmployeeDetailsFragmentArgs by navArgs() override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { val binding : FragEmployeeDetailsBinding = DataBindingUtil.inflate(inflater, R.layout.frag_employee_details,container,false) binding.employee = args.employee return binding.root }
Animate transitions between destinations
To add animations to an action, do the following:
1. In the Navigation editor, click on the action where the animation should occur.
2. In the Animations section of the Attributes panel, click the dropdown arrow next to the animation you’d like to add. You can choose between the following types:
Entering a destination
Exiting a destination
Entering a destination via a pop action
Exiting a destination via a pop action
3. Choose an animation from the list of project animations that appears.
Output will be
<fragment android:id="@+id/employeesListFragment" android:name="com.example.navigationjetpacksample.fragments.EmployeesListFragment" android:label="EmployeesListFragment" tools:layout="@layout/frag_employees_list"> <action android:id="@+id/action_employeesListFragment_to_employeeDetailsFragment" app:destination="@id/employeeDetailsFragment" app:enterAnim="@anim/enter_from_right" app:exitAnim="@anim/exit_to_left" app:popEnterAnim="@anim/enter_from_left" app:popExitAnim="@anim/exit_to_right"/> </fragment>
Create Fragments, Adapter and Activity for UI
<?xml version="1.0" encoding="utf-8"?> <layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> <data> </data> <androidx.constraintlayout.widget.ConstraintLayout android:layout_width="match_parent" android:layout_height="match_parent"> <androidx.recyclerview.widget.RecyclerView android:id="@+id/recycler_employees" android:layout_width="0dp" android:layout_height="0dp" android:paddingTop="15dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" /> <com.google.android.material.floatingactionbutton.FloatingActionButton android:id="@+id/fab_add" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" android:layout_marginEnd="16dp" android:layout_marginBottom="16dp" android:src="@android:drawable/ic_input_add" /> </androidx.constraintlayout.widget.ConstraintLayout> </layout>
package com.example.navigationjetpacksample.fragments import android.content.Context import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.databinding.DataBindingUtil import androidx.fragment.app.Fragment import androidx.navigation.findNavController import androidx.navigation.fragment.navArgs import androidx.recyclerview.widget.LinearLayoutManager import com.example.navigationjetpacksample.R import com.example.navigationjetpacksample.adapters.EmployeesListAdapter import com.example.navigationjetpacksample.databinding.FragEmployeesListBinding import com.example.navigationjetpacksample.models.Employee import com.example.navigationjetpacksample.utils.Constants.listEmployees import kotlinx.android.synthetic.main.frag_employees_list.* class EmployeesListFragment : Fragment() { private val args : EmployeesListFragmentArgs by navArgs() private var ctx: Context? = null override fun onAttach(context: Context) { super.onAttach(context) this.ctx = context } override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { val binding: FragEmployeesListBinding = DataBindingUtil.inflate( inflater, R.layout.frag_employees_list, container, false ) args.employee?.let {mEmployee -> if (args.previousScreen == AddEmployeeFragment::class.java.name) { listEmployees.add(mEmployee) } else { var pos = -1 listEmployees.forEach { pos++ if (it.id == mEmployee.id) { listEmployees[pos] = mEmployee } } } } binding.recyclerEmployees.layoutManager = LinearLayoutManager(ctx) val adapter = ctx?.let { EmployeesListAdapter(it,listEmployees) } binding.recyclerEmployees.adapter = adapter return binding.root } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) fab_add.setOnClickListener { it.findNavController().navigate(EmployeesListFragmentDirections.actionEmployeesListFragmentToAddEmployeeFragment()) } } override fun onDetach() { super.onDetach() this.ctx = null } }
<?xml version="1.0" encoding="utf-8"?> <layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> <data> <variable name="employee" type="com.example.navigationjetpacksample.models.Employee" /> </data> <androidx.cardview.widget.CardView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="15dp" app:cardCornerRadius="10dp"> <androidx.constraintlayout.widget.ConstraintLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="15dp"> <TextView android:id="@+id/txt_employee_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@{employee.firstName + ` `+ employee.lastName}" app:layout_constraintTop_toTopOf="parent" app:layout_constraintStart_toStartOf="parent" android:textSize="25sp" android:textStyle="bold"/> <ImageView android:id="@+id/img_delete" android:layout_width="20dp" android:layout_height="20dp" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toBottomOf="parent" android:src="@android:drawable/ic_menu_delete" /> <ImageView android:id="@+id/img_edit" android:layout_width="20dp" android:layout_height="20dp" app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toStartOf="@+id/img_delete" android:layout_marginEnd="15dp" android:src="@android:drawable/ic_menu_edit"/> </androidx.constraintlayout.widget.ConstraintLayout> </androidx.cardview.widget.CardView> </layout>
package com.example.navigationjetpacksample.adapters import android.content.Context import android.view.LayoutInflater import android.view.ViewGroup import androidx.databinding.DataBindingUtil import androidx.navigation.findNavController import androidx.recyclerview.widget.RecyclerView import com.example.navigationjetpacksample.R import com.example.navigationjetpacksample.databinding.FragEmployeesListRowBinding import com.example.navigationjetpacksample.fragments.EmployeesListFragmentDirections import com.example.navigationjetpacksample.models.Employee class EmployeesListAdapter (private val context: Context, private val list: MutableList<Employee>) : RecyclerView.Adapter<EmployeesListAdapter.MyViewHolder>() { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder { val inflater = LayoutInflater.from(context) val binding: FragEmployeesListRowBinding = DataBindingUtil.inflate(inflater, R.layout.frag_employees_list_row,parent,false) return MyViewHolder(binding) } override fun getItemCount(): Int { return list.size } override fun onBindViewHolder(holder: MyViewHolder, position: Int) { val getEmployee = list[position] holder.itemBinding.employee = getEmployee holder.itemBinding.root.setOnClickListener { val action = EmployeesListFragmentDirections.actionEmployeesListFragmentToEmployeeDetailsFragment(getEmployee) it.findNavController().navigate(action) } holder.itemBinding.imgEdit.setOnClickListener { val action = EmployeesListFragmentDirections.actionEmployeesListFragmentToEditEmployeeFragment(getEmployee) it.findNavController().navigate(action) } holder.itemBinding.imgDelete.setOnClickListener { val action = EmployeesListFragmentDirections.actionEmployeesListFragmentToDeleteEmployeeFragment(getEmployee) it.findNavController().navigate(action) } } class MyViewHolder(val itemBinding: FragEmployeesListRowBinding) : RecyclerView.ViewHolder(itemBinding.root){ private var binding : FragEmployeesListRowBinding? = null init { this.binding = itemBinding } } }
<?xml version="1.0" encoding="utf-8"?> <layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> <data> </data> <androidx.constraintlayout.widget.ConstraintLayout android:layout_width="match_parent" android:layout_height="match_parent"> <EditText android:id="@+id/edt_first_name" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="25dp" android:layout_marginTop="25dp" android:layout_marginEnd="25dp" android:hint="Please enter first name" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> <EditText android:id="@+id/edt_last_name" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginTop="15dp" android:hint="Please enter last name" app:layout_constraintEnd_toEndOf="@+id/edt_first_name" app:layout_constraintStart_toStartOf="@+id/edt_first_name" app:layout_constraintTop_toBottomOf="@+id/edt_first_name" /> <EditText android:id="@+id/edt_email" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginTop="15dp" android:hint="Please enter email" android:inputType="textEmailAddress" app:layout_constraintEnd_toEndOf="@+id/edt_first_name" app:layout_constraintStart_toStartOf="@+id/edt_first_name" app:layout_constraintTop_toBottomOf="@+id/edt_last_name" /> <EditText android:id="@+id/edt_phone_no" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginTop="15dp" android:hint="Please enter phone no" android:inputType="phone" app:layout_constraintEnd_toEndOf="@+id/edt_first_name" app:layout_constraintStart_toStartOf="@+id/edt_first_name" app:layout_constraintTop_toBottomOf="@+id/edt_email" /> <EditText android:id="@+id/edt_age" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginTop="15dp" android:hint="Please enter age" app:layout_constraintEnd_toEndOf="@+id/edt_first_name" app:layout_constraintStart_toStartOf="@+id/edt_first_name" app:layout_constraintTop_toBottomOf="@+id/edt_phone_no" android:inputType="number"/> <EditText android:id="@+id/edt_salary" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginTop="15dp" android:hint="Please enter salary" app:layout_constraintEnd_toEndOf="@+id/edt_first_name" app:layout_constraintStart_toStartOf="@+id/edt_first_name" app:layout_constraintTop_toBottomOf="@+id/edt_age" android:inputType="number"/> <Button android:id="@+id/btn_add" android:layout_width="100dp" android:layout_height="50dp" android:layout_marginTop="50dp" android:text="Submit" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/edt_salary" /> </androidx.constraintlayout.widget.ConstraintLayout> </layout>
package com.example.navigationjetpacksample.fragments import android.content.Context import android.os.Bundle import android.text.TextUtils import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.Toast import androidx.databinding.DataBindingUtil import androidx.fragment.app.Fragment import androidx.navigation.findNavController import androidx.navigation.fragment.navArgs import com.example.navigationjetpacksample.R import com.example.navigationjetpacksample.databinding.FragAddEmployeeBinding import com.example.navigationjetpacksample.models.Employee import kotlinx.android.synthetic.main.frag_add_employee.* import kotlinx.android.synthetic.main.frag_edit_employee.* import kotlinx.android.synthetic.main.frag_edit_employee.edt_age import kotlinx.android.synthetic.main.frag_edit_employee.edt_email import kotlinx.android.synthetic.main.frag_edit_employee.edt_first_name import kotlinx.android.synthetic.main.frag_edit_employee.edt_last_name import kotlinx.android.synthetic.main.frag_edit_employee.edt_phone_no import kotlinx.android.synthetic.main.frag_edit_employee.edt_salary import kotlin.random.Random class AddEmployeeFragment : Fragment() { private var ctx: Context? = null override fun onAttach(context: Context) { super.onAttach(context) this.ctx = context } override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { val binding : FragAddEmployeeBinding = DataBindingUtil.inflate(inflater,R.layout.frag_add_employee,container,false) return binding.root } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) btn_add.setOnClickListener { val firstName = edt_first_name.text.toString() val lastName = edt_last_name.text.toString() val email = edt_email.text.toString() val phoneNo = edt_phone_no.text.toString() val age = edt_age.text.toString() val salary = edt_salary.text.toString() if(!TextUtils.isEmpty(firstName) && !TextUtils.isEmpty(lastName) && !TextUtils.isEmpty(email) && !TextUtils.isEmpty(phoneNo) && !TextUtils.isEmpty(age) && !TextUtils.isEmpty(salary)){ val randomNo = Random.nextInt(97) + 4; val newEmployee = Employee(randomNo,firstName,lastName,email,phoneNo,age,salary) val action = AddEmployeeFragmentDirections.actionAddEmployeeFragmentToEmployeesListFragment(newEmployee,AddEmployeeFragment::class.java.name) it.findNavController().navigate(action) } else{ Toast.makeText(ctx,"All fields are required", Toast.LENGTH_SHORT).show() } } } override fun onDetach() { super.onDetach() this.ctx = null } }
<?xml version="1.0" encoding="utf-8"?> <layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> <data> <variable name="employee" type="com.example.navigationjetpacksample.models.Employee" /> </data> <androidx.constraintlayout.widget.ConstraintLayout android:layout_width="match_parent" android:layout_height="match_parent"> <EditText android:id="@+id/edt_first_name" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="25dp" android:layout_marginTop="25dp" android:layout_marginEnd="25dp" android:hint="Please enter first name" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" android:text="@{employee.firstName}"/> <EditText android:id="@+id/edt_last_name" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginTop="15dp" android:hint="Please enter last name" app:layout_constraintEnd_toEndOf="@+id/edt_first_name" app:layout_constraintStart_toStartOf="@+id/edt_first_name" app:layout_constraintTop_toBottomOf="@+id/edt_first_name" android:text="@{employee.lastName}"/> <EditText android:id="@+id/edt_email" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginTop="15dp" android:hint="Please enter email" android:inputType="textEmailAddress" app:layout_constraintEnd_toEndOf="@+id/edt_first_name" app:layout_constraintStart_toStartOf="@+id/edt_first_name" app:layout_constraintTop_toBottomOf="@+id/edt_last_name" android:text="@{employee.email}"/> <EditText android:id="@+id/edt_phone_no" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginTop="15dp" android:hint="Please enter email" android:inputType="phone" app:layout_constraintEnd_toEndOf="@+id/edt_first_name" app:layout_constraintStart_toStartOf="@+id/edt_first_name" app:layout_constraintTop_toBottomOf="@+id/edt_email" android:text="@{employee.phoneNo}"/> <EditText android:id="@+id/edt_age" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginTop="15dp" android:hint="Please enter age" app:layout_constraintEnd_toEndOf="@+id/edt_first_name" app:layout_constraintStart_toStartOf="@+id/edt_first_name" app:layout_constraintTop_toBottomOf="@+id/edt_phone_no" android:inputType="number" android:text="@{employee.age}"/> <EditText android:id="@+id/edt_salary" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginTop="15dp" android:hint="Please enter salary" app:layout_constraintEnd_toEndOf="@+id/edt_first_name" app:layout_constraintStart_toStartOf="@+id/edt_first_name" app:layout_constraintTop_toBottomOf="@+id/edt_age" android:inputType="number" android:text="@{employee.salary}"/> <Button android:id="@+id/btn_edit" android:layout_width="100dp" android:layout_height="50dp" android:layout_marginTop="50dp" android:text="Submit" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/edt_salary" /> </androidx.constraintlayout.widget.ConstraintLayout> </layout>
package com.example.navigationjetpacksample.fragments import android.content.Context import android.os.Bundle import android.text.TextUtils import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.Toast import androidx.databinding.DataBindingUtil import androidx.fragment.app.Fragment import androidx.navigation.findNavController import androidx.navigation.fragment.navArgs import com.example.navigationjetpacksample.R import com.example.navigationjetpacksample.databinding.FragEditEmployeeBinding import com.example.navigationjetpacksample.models.Employee import kotlinx.android.synthetic.main.frag_edit_employee.* class EditEmployeeFragment : Fragment() { private val args: EditEmployeeFragmentArgs by navArgs() private var ctx: Context? = null override fun onAttach(context: Context) { super.onAttach(context) this.ctx = context } override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { val binding : FragEditEmployeeBinding = DataBindingUtil.inflate(inflater, R.layout.frag_edit_employee,container,false) binding.employee = args.employee return binding.root } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) btn_edit.setOnClickListener { val firstName = edt_first_name.text.toString() val lastName = edt_last_name.text.toString() val email = edt_email.text.toString() val phoneNo = edt_phone_no.text.toString() val age = edt_age.text.toString() val salary = edt_salary.text.toString() if(!TextUtils.isEmpty(firstName) && !TextUtils.isEmpty(lastName) && !TextUtils.isEmpty(email) && !TextUtils.isEmpty(phoneNo) && !TextUtils.isEmpty(age) && !TextUtils.isEmpty(salary)){ val newEmployee = Employee(args.employee.id,firstName,lastName,email,phoneNo,age,salary) val action = EditEmployeeFragmentDirections.actionEditEmployeeFragmentToEmployeesListFragment(newEmployee,EditEmployeeFragment::class.java.name) it.findNavController().navigate(action) } else{ Toast.makeText(ctx,"All fields are required",Toast.LENGTH_SHORT).show() } } } override fun onDetach() { super.onDetach() this.ctx = null } }
<?xml version="1.0" encoding="utf-8"?> <layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> <data> </data> <androidx.constraintlayout.widget.ConstraintLayout android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent" android:text="Are you sure want to delete this employee?" app:layout_constraintVertical_bias="0.35" android:textSize="25sp" android:textStyle="bold" android:gravity="center"/> <Button android:id="@+id/btn_cancel" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Cancel" app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toStartOf="@+id/btn_submit" app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toBottomOf="parent" android:textAllCaps="false" app:layout_constraintVertical_bias="0.55"/> <Button android:id="@+id/btn_submit" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Submit" app:layout_constraintStart_toEndOf="@+id/btn_cancel" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toBottomOf="parent" android:textAllCaps="false" app:layout_constraintVertical_bias="0.55"/> </androidx.constraintlayout.widget.ConstraintLayout> </layout>
package com.example.navigationjetpacksample.fragments import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.databinding.DataBindingUtil import androidx.fragment.app.Fragment import androidx.navigation.findNavController import androidx.navigation.fragment.navArgs import com.example.navigationjetpacksample.R import com.example.navigationjetpacksample.databinding.FragDeleteEmployeeBinding import com.example.navigationjetpacksample.utils.Constants import kotlinx.android.synthetic.main.frag_delete_employee.* class DeleteEmployeeFragment : Fragment() { private val args : DeleteEmployeeFragmentArgs by navArgs() override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { val binding : FragDeleteEmployeeBinding = DataBindingUtil.inflate(inflater, R.layout.frag_delete_employee,container,false) return binding.root } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) btn_cancel.setOnClickListener { it.findNavController().popBackStack() } btn_submit.setOnClickListener { Constants.listEmployees.remove(args.employee) it.findNavController().navigate(DeleteEmployeeFragmentDirections.actionDeleteEmployeeFragmentToEmployeesListFragment2()) } } }
<?xml version="1.0" encoding="utf-8"?> <layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> <data> <variable name="employee" type="com.example.navigationjetpacksample.models.Employee" /> </data> <androidx.constraintlayout.widget.ConstraintLayout android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@+id/txt_first_name" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="25dp" android:layout_marginTop="25dp" android:layout_marginEnd="25dp" android:text="@{`First Name: ` + employee.firstName}" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> <TextView android:id="@+id/txt_last_name" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginTop="15dp" android:text="@{`Last Name: ` + employee.lastName}" app:layout_constraintEnd_toEndOf="@+id/txt_first_name" app:layout_constraintStart_toStartOf="@+id/txt_first_name" app:layout_constraintTop_toBottomOf="@+id/txt_first_name" /> <TextView android:id="@+id/txt_email" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginTop="15dp" android:text="@{`Email: ` + employee.email}" app:layout_constraintEnd_toEndOf="@+id/txt_first_name" app:layout_constraintStart_toStartOf="@+id/txt_first_name" app:layout_constraintTop_toBottomOf="@+id/txt_last_name" /> <TextView android:id="@+id/txt_phone_no" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginTop="15dp" android:text="@{`Phone No: ` + employee.phoneNo}" app:layout_constraintEnd_toEndOf="@+id/txt_first_name" app:layout_constraintStart_toStartOf="@+id/txt_first_name" app:layout_constraintTop_toBottomOf="@+id/txt_email" /> <TextView android:id="@+id/txt_age" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginTop="15dp" app:layout_constraintEnd_toEndOf="@+id/txt_first_name" app:layout_constraintStart_toStartOf="@+id/txt_first_name" app:layout_constraintTop_toBottomOf="@+id/txt_phone_no" android:text="@{`Age: ` + employee.age}"/> <TextView android:id="@+id/txt_salary" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginTop="15dp" android:text="@{`Salary: ` + employee.salary}" app:layout_constraintEnd_toEndOf="@+id/txt_first_name" app:layout_constraintStart_toStartOf="@+id/txt_first_name" app:layout_constraintTop_toBottomOf="@+id/txt_age" /> </androidx.constraintlayout.widget.ConstraintLayout> </layout>
package com.example.navigationjetpacksample.fragments import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.databinding.DataBindingUtil import androidx.fragment.app.Fragment import androidx.navigation.fragment.navArgs import com.example.navigationjetpacksample.R import com.example.navigationjetpacksample.databinding.FragEmployeeDetailsBinding class EmployeeDetailsFragment : Fragment() { private val args : EmployeeDetailsFragmentArgs by navArgs() override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { val binding : FragEmployeeDetailsBinding = DataBindingUtil.inflate(inflater, R.layout.frag_employee_details,container,false) binding.employee = args.employee return binding.root } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) } }
package com.example.navigationjetpacksample.activities import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import androidx.databinding.DataBindingUtil import androidx.recyclerview.widget.LinearLayoutManager import com.example.navigationjetpacksample.R import com.example.navigationjetpacksample.databinding.ActivityMainBinding import com.example.navigationjetpacksample.models.Employee import com.example.navigationjetpacksample.utils.Constants.listEmployees class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val binding: ActivityMainBinding = DataBindingUtil.setContentView(this@MainActivity, R.layout.activity_main) listEmployees = mutableListOf() listEmployees.add(Employee(1,"Roberto","Sanchez","rob@san.com","423424244","37","324324")) listEmployees.add(Employee(2,"Luis","Hernandez","lui@her.com","368562411","32","789218")) listEmployees.add(Employee(3,"David","Robertson","dav@rob.com","640234284","35","565787")) } }
Final Navigation Graph
<?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/employeesListFragment"> <fragment android:id="@+id/employeesListFragment" android:name="com.example.navigationjetpacksample.fragments.EmployeesListFragment" android:label="EmployeesListFragment" tools:layout="@layout/frag_employees_list"> <action android:id="@+id/action_employeesListFragment_to_employeeDetailsFragment" app:destination="@id/employeeDetailsFragment" app:enterAnim="@anim/enter_from_right" app:exitAnim="@anim/exit_to_left" app:popEnterAnim="@anim/enter_from_left" app:popExitAnim="@anim/exit_to_right"/> <action android:id="@+id/action_employeesListFragment_to_editEmployeeFragment" app:destination="@id/editEmployeeFragment" app:enterAnim="@anim/enter_from_right" app:exitAnim="@anim/exit_to_left" app:popEnterAnim="@anim/enter_from_left" app:popExitAnim="@anim/exit_to_right"/> <action android:id="@+id/action_employeesListFragment_to_deleteEmployeeFragment" app:destination="@id/deleteEmployeeFragment" app:enterAnim="@anim/enter_from_right" app:exitAnim="@anim/exit_to_left" app:popEnterAnim="@anim/enter_from_left" app:popExitAnim="@anim/exit_to_right"/> <action android:id="@+id/action_employeesListFragment_to_addEmployeeFragment" app:destination="@id/addEmployeeFragment" app:enterAnim="@anim/enter_from_right" app:exitAnim="@anim/exit_to_left" app:popEnterAnim="@anim/enter_from_left" app:popExitAnim="@anim/exit_to_right"/> <argument android:name="employee" app:argType="com.example.navigationjetpacksample.models.Employee" android:defaultValue="@null" app:nullable="true"/> <argument android:name="previousScreen" app:argType="string" android:defaultValue="@null" app:nullable="true"/> </fragment> <fragment android:id="@+id/addEmployeeFragment" android:name="com.example.navigationjetpacksample.fragments.AddEmployeeFragment" android:label="AddEmployeeFragment" tools:layout="@layout/frag_add_employee"> <action android:id="@+id/action_addEmployeeFragment_to_employeesListFragment" app:destination="@id/employeesListFragment" app:popUpTo="@id/employeesListFragment" app:popUpToInclusive="true" app:launchSingleTop="true" /> </fragment> <fragment android:id="@+id/employeeDetailsFragment" android:name="com.example.navigationjetpacksample.fragments.EmployeeDetailsFragment" android:label="EmployeeDetailsFragment" tools:layout="@layout/frag_employee_details"> <argument android:name="employee" app:argType="com.example.navigationjetpacksample.models.Employee" /> </fragment> <fragment android:id="@+id/editEmployeeFragment" android:name="com.example.navigationjetpacksample.fragments.EditEmployeeFragment" android:label="EditEmployeeFragment" tools:layout="@layout/frag_edit_employee"> <argument android:name="employee" app:argType="com.example.navigationjetpacksample.models.Employee" /> <action android:id="@+id/action_editEmployeeFragment_to_employeesListFragment" app:destination="@id/employeesListFragment" app:enterAnim="@anim/enter_from_right" app:exitAnim="@anim/exit_to_left" app:launchSingleTop="true" app:popUpTo="@id/employeesListFragment" app:popUpToInclusive="true" /> </fragment> <fragment android:id="@+id/deleteEmployeeFragment" android:name="com.example.navigationjetpacksample.fragments.DeleteEmployeeFragment" android:label="DeleteEmployeeFragment" tools:layout="@layout/frag_delete_employee"> <action android:id="@+id/action_deleteEmployeeFragment_to_employeesListFragment2" app:destination="@id/employeesListFragment" app:popUpTo="@id/employeesListFragment" app:popUpToInclusive="true" app:launchSingleTop="true" /> <argument android:name="employee" app:argType="com.example.navigationjetpacksample.models.Employee" /> </fragment> </navigation>
Easy to understand
Perfect demo to understand jetpack navigation
Very useful example
It's a good article