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.
1 Comment
I tried to follow your discussion and half of the code isn’t even available. Is there a way to get the rest of the code?