Architecture Components

Navigation Architecture Component in Android

In this post, I’ll show you how to implement the navigation architecture component in your app in Android. For demonstration will create a sample app and will integrate the navigation component in this app. This sample app contains the bottom navigation bar and toolbar menu with navigation components. So let’s get started.

Open the Android Studio and create a new project with Androidx.

Let’s move to Android Studio to create a new project with default template.

Navigate the project build.gradle and add below classpath

Let’s navigate project level build.gradle and below line.

  def nav_version = "2.1.0"
  classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version"
Apply Navigation Safeargs Plugin.

Now open the app level project build.gradle and this line on top of the file. This plug is helped us a lot in navigation, action and sending argument as well.

apply plugin: "androidx.navigation.safeargs"
Add below dependencies
  def nav_version = "1.0.0"
  def material_version = "1.2.0-alpha03"
  implementation "android.arch.navigation:navigation-fragment:$nav_version"
  implementation "android.arch.navigation:navigation-ui:$nav_version"
  implementation "com.google.android.material:material:$material_version"

Check out the latest version of navigation library here

Now add dimens inside the dimens.xml

Let’s add below dimen in that resource file.

<?xml version="1.0" encoding="utf-8"?>
<resources>
  <dimen name="padding_large">16dp</dimen>
  <dimen name="text_large">22sp</dimen>
  <dimen name="margin_large">16dp</dimen>
</resources>
Open String.xml and update below entries.
<resources>
  <string name="app_name">Navigation Example</string>
  <string name="hello_blank_fragment">Hello blank fragment</string>
  <string name="home">Home</string>
  <string name="cart">Cart</string>
  <string name="shop">Shop</string>
  <string name="about_us">About Us</string>
  <string name="notification">Notifications</string>
  <string name="view_profile">View Profile</string>
  <string name="welcome_navigation_example_application">Welcome \nNavigation Example Application</string>
  <string name="notification_fragment">Notification Fragment</string>
  <string name="cart_fragment">Cart Fragment</string>
  <string name="cart_detail">Cart Detail</string>
  <string name="view_product_with_arguments">View Product with arguments</string>
  <string name="profile_fragment">Profile</string>
  <string name="product_detail">Product Details</string>
  <string name="string_count">Total Products Count</string>
  <string name="name_lable">Product Name -</string>
</resources>
Create a menu resource file toolbar_menu.xml

For showing menu in the toolbar will create menu file named is toolbar_menu.xml

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
	xmlns:app="http://schemas.android.com/apk/res-auto">
	<item
		android:id="@+id/cart_destination"
		android:icon="@drawable/ic_shopping_cart"
		android:title="@string/cart"
		app:showAsAction="ifRoom" />
</menu>
Create res menu file for Bottom Navigation named is bottom_nav_menu.xml

For showing bottom navigation in main activity, I’m creating another menu for that.

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
	<item
		android:id="@+id/home_destination"
		android:icon="@drawable/ic_home"
		android:title="@string/home" />
	<item
		android:id="@+id/notification_destination"
		android:icon="@drawable/ic_notifications"
		android:title="@string/notification" />
</menu>
Open main activity layout file and add below code

In main activity layout file contains NavHostFragment and BottomNaviagtion in portrait mode.

<?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="0dp"
      android:layout_height="0dp"
      android:layout_weight="1"
      app:defaultNavHost="true"
      app:layout_constraintBottom_toTopOf="@+id/bottom_nav"
      app:layout_constraintEnd_toEndOf="parent"
      app:layout_constraintStart_toStartOf="parent"
      app:layout_constraintTop_toTopOf="parent"
      app:navGraph="@navigation/nav_graph"
      />

  <com.google.android.material.bottomnavigation.BottomNavigationView
      android:id="@+id/bottom_nav"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:backgroundTint="@color/colorAccent"
      app:layout_constraintBottom_toBottomOf="parent"
      app:layout_constraintEnd_toEndOf="parent"
      app:layout_constraintStart_toStartOf="parent"
      android:background="@color/colorPrimary"
      app:itemIconTint="@color/white"
      app:itemTextColor="@color/white"
      app:menu="@menu/bottom_nav_menu"
      />

</androidx.constraintlayout.widget.ConstraintLayout>
For landscape mode create another layout that has NavigationView.

Create a new layout file for the landscape model with same name. In landscape mode we will show side navigation.

<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout 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/drawer_layout"
    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="wrap_content"
      android:layout_weight="1"
      app:defaultNavHost="true"
      app:navGraph="@navigation/nav_graph"
      />

  <com.google.android.material.navigation.NavigationView
      android:id="@+id/nav_view"
      android:layout_width="wrap_content"
      android:layout_height="match_parent"
      android:layout_gravity="start"
      app:menu="@menu/bottom_nav_menu"
      />

</androidx.drawerlayout.widget.DrawerLayout>
Finally, configure navigation component code inside MainActivity.

Open the main activity, In this activity, we are setting bottom navigation, side navigation (for landscape mode) and setting up action menu as well.

For doing all things we are using Navigation Component only.

package com.navigation.example;

import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.drawerlayout.widget.DrawerLayout;
import androidx.navigation.NavController;
import androidx.navigation.Navigation;
import androidx.navigation.ui.NavigationUI;
import com.google.android.material.bottomnavigation.BottomNavigationView;

public class MainActivity extends AppCompatActivity {

  private BottomNavigationView bottomNavigationView;
  private NavController navController;
  private DrawerLayout drawerLayout;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    navController = Navigation.findNavController(this, R.id.nav_host_fragment);
    bottomNavigationView = findViewById(R.id.bottom_nav);
    drawerLayout = findViewById(R.id.drawer_layout);

    setUpBottomNav(navController);
    setUpSideNav(navController);
    setUpActionBar(navController);
  }

  private void setUpBottomNav(NavController navController) {
    NavigationUI.setupWithNavController(bottomNavigationView, navController);
  }

  private void setUpSideNav(NavController navController) {
    NavigationUI.setupWithNavController(bottomNavigationView, navController);
  }

  private void setUpActionBar(NavController navController) {
    NavigationUI.setupActionBarWithNavController(this, navController, drawerLayout);
  }

  @Override
  public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.toolbar_menu, menu);
    return true;
  }

  @Override
  public boolean onOptionsItemSelected(@NonNull MenuItem item) {
    boolean navigated = NavigationUI.onNavDestinationSelected(item, navController);
    return navigated || super.onOptionsItemSelected(item);
  }

  @Override
  public boolean onSupportNavigateUp() {
    return NavigationUI.navigateUp(
        Navigation.findNavController(this, R.id.nav_host_fragment), drawerLayout);
  }
}
Navigation resource file

in res create a resource folder name is navigation and create navigation graph file. In file name, I’m taken here nav_graph.xml.

Basically, followings things we are doing here

  • Setting up navigation Id
  • Set start destination here is a home fragment
<?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/home_destination">
</navigation>
  • Declear fragments here
<fragment
      android:id="@+id/home_destination"
      android:name="com.navigation.example.fragments.HomeFragment"
      android:label="Home"
      tools:layout="@layout/fragment_home">
</fragment>
  • Setup action and action destination
    <action
        android:id="@+id/next_action"
        app:destination="@+id/profile_destination" />
  • Setup safe argument as well
    <android:name="com.navigation.example.fragments.ProductFragment"
      android:label="Product"
      tools:layout="@layout/fragment_product">

    <argument
        android:name="product_name"
        app:argType="string"
        app:nullable="true" />
    <argument
        android:name="amount"
        app:argType="float"
        android:defaultValue="0.0" />
    <argument
        android:name="item_count"
        app:argType="integer"
        android:defaultValue="0" />
  </fragment>
Finally, your nav_graph.xml code looks like this.
<?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/home_destination">

  <fragment
      android:id="@+id/home_destination"
      android:name="com.navigation.example.fragments.HomeFragment"
      android:label="Home"
      tools:layout="@layout/fragment_home">
    <action
        android:id="@+id/next_action"
        app:destination="@+id/profile_destination" />
  </fragment>

  <fragment
      android:id="@+id/notification_destination"
      android:name="com.navigation.example.fragments.NotificationFragment"
      android:label="Notification"
      tools:layout="@layout/fragment_notification" />
  <fragment

      android:id="@+id/profile_destination"
      android:name="com.navigation.example.fragments.ProfileFragment"
      android:label="Home"
      tools:layout="@layout/fragment_profile">
    <argument
        android:name="productCount"
        android:defaultValue="0"
        app:argType="integer" />
  </fragment>

  <fragment
      android:id="@+id/cart_destination"
      android:name="com.navigation.example.fragments.CartFragment"
      android:label="Cart"
      tools:layout="@layout/fragment_cart">
    <action
        android:id="@+id/next_action"
        app:destination="@+id/product_destination" />
  </fragment>

  <fragment
      android:id="@+id/product_destination"
      android:name="com.navigation.example.fragments.ProductFragment"
      android:label="Product"
      tools:layout="@layout/fragment_product">

    <argument
        android:name="product_name"
        app:argType="string"
        app:nullable="true" />
    <argument
        android:name="amount"
        app:argType="float"
        android:defaultValue="0.0" />
    <argument
        android:name="item_count"
        app:argType="integer"
        android:defaultValue="0" />
  </fragment>


</navigation>
Open HomeFragment and on button click navigate another fragment.

On button click, we are fetching the direction and next action.

package com.navigation.example.fragments;

import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.navigation.NavController;
import androidx.navigation.Navigation;
import com.navigation.example.R;

/**
 * A HomeFragment {@link Fragment} subclass.
 */
public class HomeFragment extends Fragment {

  @Override
  public View onCreateView(LayoutInflater inflater, ViewGroup container,
      Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    return inflater.inflate(R.layout.fragment_home, container, false);
  }

  @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    Button viewProfile = view.findViewById(R.id.buttonViewProfile);
    viewProfile.setOnClickListener(new View.OnClickListener() {
      @Override public void onClick(View view) {
        // find navigation
        NavController navController = Navigation.findNavController(view);
        navController.navigate(HomeFragmentDirections.nextAction());
        //One line also can do like this
        // Navigation.findNavController(view).navigate(HomeFragmentDirections.nextAction());
      }
    });
  }
}
Open CartFragment and add below code

On view product button click will move to ProductFragment as pass some arguments.

package com.navigation.example.fragments;

import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.navigation.NavController;
import androidx.navigation.Navigation;
import com.navigation.example.R;

/**
 * A simple {@link Fragment} subclass.
 */
public class CartFragment extends Fragment {

  @Override
  public View onCreateView(LayoutInflater inflater, ViewGroup container,
      Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    return inflater.inflate(R.layout.fragment_cart, container, false);
  }

  @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    Button buttonViewProduct = view.findViewById(R.id.buttonViewProduct);
    buttonViewProduct.setOnClickListener(new View.OnClickListener() {
      @Override public void onClick(View view) {

        CartFragmentDirections.NextAction nextAction =
            CartFragmentDirections.nextAction("This is a sample product");
        nextAction.setAmount(100.00f);
        nextAction.setItemCount(2);

        NavController navController = Navigation.findNavController(view);
        navController.navigate(nextAction);
      }
    });
  }
}
Get argument using safe argument
 package com.navigation.example.fragments;

import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import com.navigation.example.R;

/**
 * ProductFragment  {@link Fragment} subclass.
 */
public class ProductFragment extends Fragment {

  public ProductFragment() {
    // Required empty public constructor
  }

  @Override
  public View onCreateView(LayoutInflater inflater, ViewGroup container,
      Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    return inflater.inflate(R.layout.fragment_product, container, false);
  }

  @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    TextView tvInfo = view.findViewById(R.id.tv_product_info);

    ProductFragmentArgs args = ProductFragmentArgs.fromBundle(getArguments());
    //String name = args.getProductName();
    //Float amount = args.getAmount();
    //Integer itemCount = args.getItemCount();

    tvInfo.setText(getString(R.string.name_lable)
        + args.getProductName()
        + "\n" +
        " Count "
        + args.getItemCount()
        + "\n" +
        " Amount "
        + args.getAmount());
  }
}

Conclusion

With the help of this navigation component android tutorial, We have learned how to implement navigation android architecture components in Android. I hope it’s helpful for you, Help me by sharing this post with all your friends who learning android app development.

Get Solution Code

Keep in touch

If you want to keep in touch and get an email when I write new blog posts, Still, if you have any queries please put your comment below.

Check out the architecture components tutorial series

Subscribe
Notify of
1 Comment
Oldest
Newest Most Voted
Inline Feedbacks
View all comments