Android Bottom Navigation Bar Example - Truiton
Skip to content

Android Bottom Navigation Bar Example

Android Bottom Navigation Bar

Its been a while since Google introduced Material Design, but recently with Design Support Library v25 they released a new widget to make an Android Bottom Navigation Bar, as described in the official material design specs. This new navigation component is called the BottomNavigationView and as mentioned, its packaged under the design support library, having full backward support. Although if you browse the internet, you may find many examples, showing how to implement an Android bottom navigation bar. But this new Android BottomNavigationView widget makes it very easy for the developers to build and deploy apps with bottom navigation, as its an official component.

Android BottomNavigationView Widget

At first when you look at the new BottomNavigationView widget it may look similar to the TabLayout of the same library. But but do not get confused, as its implementation is a lot different than that of the later one. As the new bottom bar navigation implementation of Android is based out of menu items. Hence to populate a BottomNavigationView you need to specify a menu resource file, unlike in the TabLayout. Although if you look at the final output i.e. the screen, there is still a striking similarity between the two. But putting this discussion to rest, lets have a look at the new features of the Android BottomNavigationView.

Whenever a new component is introduced, along with it some new methods and attributes are also added with it. Hence with the Android’s official bottom navigation widget the BottomNavigationView following new XML attributes are added:

android bottom navigation bar

As I mentioned BottomNavigationView takes a menu resource file to inflate the navigation items. To do so following are the ways in which it can be done:

Once a BottomNavigationView is inflated and visible, a click listener can be attached to it:

Method used to select a specific item in the BottomNavigationView:

  • BottomNavigationView.getMenu().getItem(index).setChecked(true);

Although this component gives us the flexibility of changing screen content dynamically. But it is advised to not implement swiping views with an Android bottom navigation bar as per specs. Therefore this rules out the possibility of using a ViewPager with the bottom navigation bar. Instead a simple view or a set of fragments for complex implementation can be used. Therefore here in this tutorial, I will show how to implement a BottomNavigationView with a set of fragments. Lets have look at the example below.

Android Bottom Navigation Bar Example

To demonstrate a working example of Android BottomNavigationView widget, I would make three fragments and switch between them by using the bottom navigation bar. Here are the steps:

Step 1 : Add the dependencies

To start off with an example of bottom navigation bar on android , first we need to include following dependencies in our build.gradle file.

compile 'com.android.support:appcompat-v7:25.1.0'
compile 'com.android.support:design:25.1.0'
compile 'com.android.support:support-v4:25.1.0'

 

Step 2 : Define the Fragments

For this example I will be building a screen with three fragments, which could be switched by the BottomNavigationView. Hence before jumping on to the main screen, lets define three fragments.

Fragment 1:

<RelativeLayout 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="com.truiton.bottomnavigation.ItemOneFragment">

    <ImageView
        android:id="@+id/truiton_image"
        android:layout_width="300dp"
        android:layout_height="300dp"
        android:layout_centerInParent="true"
        android:src="@mipmap/truiton"/>

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/truiton_image"
        android:layout_centerHorizontal="true"
        android:text="Fragment 1"
        android:textSize="30sp"/>

</RelativeLayout>
package com.truiton.bottomnavigation;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

public class ItemOneFragment extends Fragment {
    public static ItemOneFragment newInstance() {
        ItemOneFragment fragment = new ItemOneFragment();
        return fragment;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_item_one, container, false);
    }
}

Fragment 2:

<RelativeLayout 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="com.truiton.bottomnavigation.ItemTwoFragment">

    <ImageView
        android:id="@+id/truiton_image"
        android:layout_width="300dp"
        android:layout_height="300dp"
        android:layout_centerInParent="true"
        android:src="@mipmap/truiton"/>

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/truiton_image"
        android:layout_centerHorizontal="true"
        android:text="Fragment 2"
        android:textSize="30sp"/>

</RelativeLayout>
package com.truiton.bottomnavigation;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

public class ItemTwoFragment extends Fragment {
    public static ItemTwoFragment newInstance() {
        ItemTwoFragment fragment = new ItemTwoFragment();
        return fragment;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_item_two, container, false);
    }
}

Fragment 3:

<RelativeLayout 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="com.truiton.bottomnavigation.ItemThreeFragment">

    <ImageView
        android:id="@+id/truiton_image"
        android:layout_width="300dp"
        android:layout_height="300dp"
        android:layout_centerInParent="true"
        android:src="@mipmap/truiton"/>

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/truiton_image"
        android:layout_centerHorizontal="true"
        android:text="Fragment 3"
        android:textSize="30sp"/>

</RelativeLayout>
package com.truiton.bottomnavigation;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

public class ItemThreeFragment extends Fragment {
    public static ItemThreeFragment newInstance() {
        ItemThreeFragment fragment = new ItemThreeFragment();
        return fragment;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_item_three, container, false);
    }
}

Step 3 : Defining the bottom navigation menu XML

As mentioned before to populate the actual items into an Android bottom navigation bar, a menu type XML is used. This XML should contain at minimum three attributes:

  • android:title
  • android:icon
  • android:id

For this example of BottomNavigationView, I would make a menu of three items:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:id="@+id/action_item1"
        android:icon="@drawable/ic_account_box_black_24dp"
        android:title="@string/item_1"/>
    <item
        android:id="@+id/action_item2"
        android:icon="@drawable/ic_account_circle_black_24dp"
        android:title="@string/item_2"/>
    <item
        android:id="@+id/action_item3"
        android:icon="@drawable/ic_assignment_ind_black_24dp"
        android:title="@string/item_3"/>
</menu>

Step 4 : Defining the Activity XML

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    android:id="@+id/activity_main"
    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="com.truiton.bottomnavigation.MainActivity">

    <FrameLayout
        android:id="@+id/frame_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_above="@+id/navigation"
        android:animateLayoutChanges="true">

    </FrameLayout>

    <android.support.design.widget.BottomNavigationView
        android:id="@+id/navigation"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:background="@color/colorPrimary"
        app:itemIconTint="@color/nav_item_state_list"
        app:itemTextColor="@color/nav_item_state_list"
        app:menu="@menu/bottom_navigation_items"/>
</RelativeLayout>

As you can see above, for attributes app:itemIconTint and app:itemTextColor, I have used a ColorStateList. Please make sure when you make a color state list, its according to the Material design specs for bottom navigation bar. Full source code is available at the end of the tutorial.

 

Step 5 : Defining the activity with bottom navigation bar

package com.truiton.bottomnavigation;

import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.design.widget.BottomNavigationView;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;
import android.view.MenuItem;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        BottomNavigationView bottomNavigationView = (BottomNavigationView)
                findViewById(R.id.navigation);

        bottomNavigationView.setOnNavigationItemSelectedListener
                (new BottomNavigationView.OnNavigationItemSelectedListener() {
                    @Override
                    public boolean onNavigationItemSelected(@NonNull MenuItem item) {
                        Fragment selectedFragment = null;
                        switch (item.getItemId()) {
                            case R.id.action_item1:
                                selectedFragment = ItemOneFragment.newInstance();
                                break;
                            case R.id.action_item2:
                                selectedFragment = ItemTwoFragment.newInstance();
                                break;
                            case R.id.action_item3:
                                selectedFragment = ItemThreeFragment.newInstance();
                                break;
                        }
                        FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
                        transaction.replace(R.id.frame_layout, selectedFragment);
                        transaction.commit();
                        return true;
                    }
                });

        //Manually displaying the first fragment - one time only
        FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
        transaction.replace(R.id.frame_layout, ItemOneFragment.newInstance());
        transaction.commit();

        //Used to select an item programmatically
        //bottomNavigationView.getMenu().getItem(2).setChecked(true);
    }
}

As you can see above when making a screen with the help of BottomNavigationView we have to initialize it with a default view. As there is no ViewPager here, we are doing it all manually. By default when a BottomNavigationView is initialized it is loaded with the first item selected. But if you wish to load the screen with any other item selected, you can do so by getting the menu item and setting it checked as shown above. For full source code, please refer to the following link:

Full Source Code

The final output would look like this:

Android bottom navigation bar

BottomNavigationView Limitations

Although the view itself is recently released, hence it is bound to have some issues. But if you are trying to build an Android screen with bottom navigation, here is a list of issues you might face:

  • Item Background cannot be colored for selected state.
  • It does not have a bottom navigation behavior, hence no integration is available for FAB, Snackbar, and CoordinatorLayout.
  • Ethically swiping of views should not be done – Stated in Material Design guidelines.
  • Text and icon sizes cannot be changed.
  • No way to hide title for non selected items.
  • Only 5 items can be added at a time.

But besides all this, building an Android bottom navigation bar has become a lot more simpler with the new BottomNavigationBar widget. As this is the new official component for bottom navigation. Also when speaking of shaping a product, giving upfront options like the bottom navigation has always gotten more traction, since it presents all the options to a user right away. Hope this helped, follow us on Twitter, Facebook and Google+ for more updates.

20 thoughts on “Android Bottom Navigation Bar Example”

  1. thanks nice. how to implement the back navigation on back press (e.g item1 -> item2 -> item3 then back item3 -> item2 – item1)

  2. I had search many topic related to bottom navigation bar and i tried to implement on my project exactly as per there instructions. but then i found your blog and i am so happy that your tutorial works and the way to guide it so easy to understand. thank you so much bro, have a good and blessing day…

  3. But why I don’t see the standard behavior here where the text is shown only in the case of the currect selected bottom icon?

    1. You need to use viewhelper class.

      package com.truiton.bottomnavigation;

      import android.support.design.internal.BottomNavigationItemView;
      import android.support.design.internal.BottomNavigationMenuView;
      import android.support.design.widget.BottomNavigationView;
      import android.util.Log;

      import java.lang.reflect.Field;

      /**
      * Helper class to get rid of "Shift Mode" from BottomNavigationView
      */

      public class bh {

      public static void disableShiftMode(BottomNavigationView view) {

      BottomNavigationMenuView menuView = (BottomNavigationMenuView) view.getChildAt(0);
      try {
      Field shiftingMode = menuView.getClass().getDeclaredField("mShiftingMode");
      shiftingMode.setAccessible(true);
      shiftingMode.setBoolean(menuView, false);
      shiftingMode.setAccessible(false);
      for (int i = 0; i < menuView.getChildCount(); i++) {
      BottomNavigationItemView item = (BottomNavigationItemView) menuView.getChildAt(i);
      //noinspection RestrictedApi
      item.setShiftingMode(false);
      // set once again checked value, so view will be updated
      //noinspection RestrictedApi
      item.setChecked(item.getItemData().isChecked());
      }
      } catch (NoSuchFieldException e) {
      Log.e("BNVHelper", "Unable to get shift mode field", e);
      } catch (IllegalAccessException e) {
      Log.e("BNVHelper", "Unable to change value of shift mode", e);
      }
      }
      }

  4. Thank you for this great tutorial. I started off with yours, and wanted to add two more items so that there will be 5 total. Once I added 5 items, when I click it on the phone, they animate and the icon clicked is larger and they slide slightly. While this is a nice animation, I would prefer them to be fixed and not moving/changing when clicked except for color which you have. Any suggestions? Thanks!

  5. Hey Mohit, Thanks for the clear illustration, can you add the stack management for each single tab, in the same or any clues regarding to this?

  6. thanks for the good example, i am getting one issue that on bottom navigation I am not getting the name for un-selected menu item. Only first item get selected by default and its name is visible

Leave a Reply

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