Now you can use the Bottom Navigation View in the Design Support Library

UPDATE 2016.10.26.

Added a paragraph after the list of available attributes for the control to mention how you can have a ripple effect as touch highlight if you don't set the background of the BottomNavigationView widget.

Original post

Bottom navigation with tabs has been quite a common primary navigation pattern over on iOS for a long time. While it is a little alien for many Android users, it has several merits. First of all, it sits at the bottom of the screen so it is easy to reach even while using the phone with one hand. It is always visible, making it easier to explore compared to say a Navigation Drawer. Android guidelines already included tabs too, but they were at the top of the screen, combined with swipeable pages, implemented with a ViewPager.

This spring, Google officially added Bottom Navigation to Material Design Guidelines and released new versions of its Photos and Google+ app with this component as its main navigation. The only problem was - as it is the case with many items in the spec - that there were no official implementation available for developers for this component. Third party libraries appeared soon, but the developer community wanted a solution from Google and it took them this long to release it - but it is finally here.

It is included in the Design Support Library, starting with version 25.0.0. You can include it in your build.gradle file with the following line (you'll also need the AppCompat Support Library as the Design Support Library's dependency):

compile 'com.android.support:appcompat-v7:25.0.0'  
compile 'com.android.support:design:25.0.0'  

For this article I demonstrate a basic usage of the widget. I also made a demo app which you can check out here:
https://github.com/AutSoft/BottomNavigationTest

The Design Spec

The design spec outlines a couple of traits for this component, most importantly:

  • It should be used for three to five top level destinations which require instant access.
  • They should have a light or dark grayscale background with colored icons and text, or a colored background and light or dark grayscale icons - you should not mix those and you should only use at most one color for the tabs
  • Short text labels should be displayed below every icon and tapping one of them should take you to one of the pages.
  • Contrary to (top) tabs, swiping between these pages should not be enabled - great when the content of the page requires the gesture for something else.
  • The currently selected tab should be highlighted with bigger icon and text and/or different coloring.
  • Tapping on a tab could colour the whole view with a new tint color using a ripple effect

You can read the corresponding section of the spec here:
https://material.google.com/components/bottom-navigation.html

The Widget

As I mentioned and official implementation is included in the latest Design Support Library. The documentation for it is pretty scarse and in some places even wrong at this time (though I expect it to improve). You can find it here:

https://developer.android.com/reference/android/support/design/widget/BottomNavigationView.html

Basic Example with three items

Basic Example with three items

It includes a basic example for including it in your layout resource file but it is misleading at the time of this writing, so here is a fixed version of it:

<android.support.design.widget.BottomNavigationView  
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:id="@+id/bottom_navigation_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:itemBackground="@color/darkGrey"
        app:itemIconTint="@color/bottom_navigation_item_background_colors"
        app:itemTextColor="@color/bottom_navigation_item_background_colors"
        app:menu="@menu/menu_bottom_navigation" />

It only has three xml attributes at this time:

  • itemBackground: The background color or Drawable of the items. Can be set from code with the setItemBackgroundResource() method
  • itemIconTint: The icon tint for items Can be set from code with the setItemIconTintList() method
  • itemTextColor: The text color for the item labels Can be set from code with the setItemTextColor() method

If you does not specify these attributes, the currently selected item's icon and text automatically colored with the color you specified in your app theme as colorPrimary (the other items are tinted grey) and you also get a ripple effect on touch. There does not seem to be a way to get this ripple effect when you change the background though.

It can be populated with items via a menu resource file, just like a Navigation Drawer or an Overflow menu. Please note that you can set the enabled state for each items but you cannot set the visibility of them from the menu resource file. Here is an example:

<?xml version="1.0" encoding="utf-8"?>  
<menu  
    xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:id="@+id/action_one"
        android:icon="@android:drawable/ic_dialog_map"
        android:title="One"/>
    <item
        android:id="@+id/action_two"
        android:icon="@android:drawable/ic_dialog_info"
        android:title="Two"/>
    <item
        android:id="@+id/action_three"
        android:icon="@android:drawable/ic_dialog_email"
        android:title="Three"/>
    <item
        android:id="@+id/action_four"
        android:icon="@android:drawable/ic_popup_reminder"
        android:title="Four"/>
</menu>  

The menu can be inflated from code too, with the inflateMenu() method.

It is smart about displaying these items, as if there is more than three elements, it only displays the currently selected one with icon AND text, and shifts the other ones closer together without text labels. Sadly, there isn't any way to force enable or disable this behaviour which may not work with every design. It also doesn't allow populating the Bottom Navigation View with more than five items - as per the design spec (it throws an IllegalArgumentException if you try to).

Behaviour with four items

Behaviour with four items

To achieve different tinting for selected items, you should specify a color list resource as itemBackground and itemTextColor like this:

<?xml version="1.0" encoding="utf-8"?>  
<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <item
        android:color="@color/colorAccent"
        android:state_checked="false"/>
    <item
        android:color="@android:color/white"
        android:state_checked="true"/>

</selector>  

Finally, you can listen to tab selection events by adding an BottomNavigation.OnNavigationItemSelectedListener via the setOnNavigationItemSelectedListener() method:

bottomNavigationView.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {  
    @Override
    public boolean onNavigationItemSelected(@NonNull MenuItem item) {
        Fragment fragment = null;
        switch (item.getItemId()) {
            case R.id.action_one:
                // Switch to page one
                break;
            case R.id.action_two:
                // Switch to page two
                break;
            case R.id.action_three:
                // Switch to page three
                break;
        }
        return true;
    }
});

The selected item will appear selected if you return true for the onNavigationItemSelected() method.

That's all we get for now, there is no sign of the color ripple effect or the left navigation variant which are also part of the design spec.

At the time of writing, some of the third party libraries still provide much more functionality and customization, so they may be worth checking out:

https://github.com/Ashok-Varma/BottomNavigation
https://github.com/sephiroth74/Material-BottomNavigation
https://github.com/roughike/BottomBar
https://github.com/aurelhubert/ahbottomnavigation

Thanks for the read!