Creating Bottom Navigation View by using a third-party library in Android

    In Mar 2016, Google has released a new component in Material Design Technology called Bottom Navigation Bar - providing guidance for a pattern that had already seen success on iOS. Bottom bar/tabs are understandably controversial: Android design always recommended having tabs at the top of the screen, and usage of tabs at the bottom was looked at as lazy mimicking of iOS design. Yet Google themselves began using the pattern last year with Google+, and then followed it up with Google Photos earlier this year.
    However, Bottom Navigation Bar also has excellent specific usage, like we can see at Google+ and Google Photo apps. But, in Android SDK, there is none official widget or of document to show us a solution to make this design! So, up to now, the best way is using a third-party library to create it.
    Through this post, I would like to present a simple/popular library called Bottom-Bar (developed by Iiro Krankka) which be able to creating this component after a few step.
    DEMO VIDEO:

Importing library

    The simplest way to use this library is adding it's dependency to your application level build.gradle:
compile 'com.roughike:bottom-bar:1.4.0.1'
    Now, I will make a demo project about using it to create the Bottom Navigation Bar, it's source code now available on Github.

Simple Bottom Bar with custom tabs color and background

    The object to building the Bottom Navigation bar is BottomBar. It's not a UI widget, so we don't put it in a xml file, it will be created in Java code.
    Some important method:
  • attach(): Bind the BottomBar to the specified View's parent, and inflate your layout there. Useful when the BottomBar overlaps some content that shouldn't be overlapped.
  • setItems(menu_file_id): Set items (tabs) for this BottomBar from menu file.
  • Handling any tab selected/reselected by called setOnMenuTabClickListener(). The parameter here is OnMenuTabClickListener interface and there are 2 methods that you must override:
    • onMenuTabSelected(): called when BottomBarTab first selected.
    • onMenuTabReSelected(): called when BottomBarTab reselected.
    Firstly, providing a menu file for this project, with it, we can create a Bottom Navigation Bar with 4 tabs later:
bottom_bar_menu.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:id="@+id/like"
        android:icon="@drawable/like"
        android:title="Like" />
    <item
        android:id="@+id/love"
        android:icon="@drawable/love"
        android:title="Love" />
    <item
        android:id="@+id/sad"
        android:icon="@drawable/sad"
        android:title="Sad" />

    <item
        android:id="@+id/angry"
        android:icon="@drawable/angry"
        android:title="Angry" />
</menu>
    This is a full code for an activity to creating a Bottom Navigation Bar with custom background and the tabs color will be changed when it's selected:
SimpleActivity.java
package info.devexchanges.bottomnavigation;

import android.graphics.Color;
import android.os.Bundle;
import android.support.annotation.IdRes;
import android.support.annotation.Nullable;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.widget.Toast;

import com.roughike.bottombar.BottomBar;
import com.roughike.bottombar.OnMenuTabClickListener;

public class SimpleActivity extends AppCompatActivity {

    private BottomBar mBottomBar;

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

        // Customize the colors here
        mBottomBar = BottomBar.attach(this, savedInstanceState,
                Color.parseColor("#f2f2f2"), // Background Color
                ContextCompat.getColor(this, R.color.colorAccent), // Tab Item Color
                0.25f); // Tab Item Alpha
        mBottomBar.setItems(R.menu.bottom_bar_menu);


        mBottomBar.setOnMenuTabClickListener(new OnMenuTabClickListener() {

            @Override
            public void onMenuTabSelected(@IdRes int menuItemId) {
                showToast(menuItemId, false);
            }

            @Override
            public void onMenuTabReSelected(@IdRes int menuItemId) {
                showToast(menuItemId, true);
            }
        });
    }

    private void showToast(int menuId, boolean isReselected) {
        if (menuId == R.id.like) {
            if (isReselected) {
                show("Tab Like Reselected!");
            } else {
                show("You like this!");
            }
        } else if (menuId == R.id.love) {
            if (isReselected) {
                show("Tab Love Reselected!");
            } else show("You love this!");
        } else if (menuId == R.id.sad) {
            if (isReselected) {
                show("Tab Sad Reselected");
            } else show("You felt sad when reading this content!");
        } else if (isReselected) {
            show("Tab Angry Reselected!");
        } else show("You felt angry when reading this!");
    }

    private void show(String msg) {
        Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);

        // Necessary to restore the BottomBar's state, otherwise we would
        // lose the current tab on orientation change.
        mBottomBar.onSaveInstanceState(outState);
    }
}
    Running this activity, we'l have this output:
"Love" tab first selected
"Love" tab selected

Changing Bottom Bar background when tab selected

    By using mapColorForTab() method, your BottomBar background when each tab selected. See this activity code:
ChangeBackgroundActivity.java

package info.devexchanges.bottomnavigation;

import android.os.Bundle;
import android.support.annotation.IdRes;
import android.support.annotation.Nullable;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;

import com.roughike.bottombar.BottomBar;
import com.roughike.bottombar.OnMenuTabClickListener;

public class ChangeBackgroundActivity extends AppCompatActivity {

    private BottomBar bottomBar;

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

        bottomBar = BottomBar.attach(this, savedInstanceState);
        bottomBar.setItems(R.menu.bottom_bar_menu);
        bottomBar.setOnMenuTabClickListener(new OnMenuTabClickListener() {
            @Override
            public void onMenuTabSelected(@IdRes int menuItemId) {

            }

            @Override
            public void onMenuTabReSelected(@IdRes int menuItemId) {

            }
        });

        // Setting colors for different tabs when there's more than three of them.
        // You can set colors for tabs in three different ways as shown below.
        bottomBar.mapColorForTab(0, ContextCompat.getColor(this, R.color.colorAccent));
        bottomBar.mapColorForTab(1, 0xFF5D4037);
        bottomBar.mapColorForTab(2, "#7B1FA2");
        bottomBar.mapColorForTab(3, "#FF5252");
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);

        bottomBar.onSaveInstanceState(outState);
    }
}

    Running this activity, we'll have this output:

Customizing Navigation Bar behavior

    As you can see outputs above, the bottom navigation bar overlaps the main view content, so in order to avoid this inconvenience, we should hide it when scrolling screen. Similar with another scrolling trick in Material Design tech, we must useCoordinatorLayout as the root container in the activity layout (xml file) like this:
activity_behavior.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/myCoordinator"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true">

    <android.support.v4.widget.NestedScrollView
        android:id="@+id/myScrollingContent"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:padding="16dp"
            android:text="@string/long_text" />

    </android.support.v4.widget.NestedScrollView>

</android.support.design.widget.CoordinatorLayout>
Change from BottomBar.attach() to BottomBar.attachShy() in activity Java code:
BehaviorActivity.java
package info.devexchanges.bottomnavigation;

import android.os.Bundle;
import android.support.annotation.IdRes;
import android.support.annotation.Nullable;
import android.support.design.widget.CoordinatorLayout;
import android.support.v7.app.AppCompatActivity;

import com.roughike.bottombar.BottomBar;
import com.roughike.bottombar.OnMenuTabClickListener;

public class BehaviorActivity extends AppCompatActivity {

    private BottomBar bottomBar;

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

        bottomBar = BottomBar.attachShy((CoordinatorLayout) findViewById(R.id.myCoordinator),
                findViewById(R.id.myScrollingContent), savedInstanceState);
        bottomBar.setItems(R.menu.bottom_bar_menu);

        bottomBar.setOnMenuTabClickListener(new OnMenuTabClickListener() {
            @Override
            public void onMenuTabSelected(@IdRes int menuItemId) {

            }

            @Override
            public void onMenuTabReSelected(@IdRes int menuItemId) {

            }
        });
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);

        bottomBar.onSaveInstanceState(outState);
    }
}
    We'll have this output:

    More over, you can easily add badges for showing an unread message count or new items/ /whatever you like. Read Badge guide of this library to learn the way to make this output:

Conclusions

    What do you think about bottom navigation? An improvement over tabs or change for change’s sake? This component is controversial in Android design but we can not deny its usefulness. Beside that, there are 2 widget that similar with it called Bottom Sheet and Modal Bottom Sheet, I had 2 posts about them (following links), you should take a glance. After all, this is an emerging pattern (or re-emerging, depending on who you ask) on Android, so the nuances of how the bar should be used aren't set in stone. As always, developers and designers should weigh what makes sense in their own context for their own product, using the guidelines as general best practices for any patterns they find to be necessary.

Update: Bottom Navigation View in Android SDK

    Finally, Google developers released Design Support Library version 25.0.0 and providing a new widget named BottomNavigationView. With this, we now have an official way to build a bottom navigation view which not depend on a third-party library. Please read my UPDATE POST to learning this new solution.
      References:

Share


Previous post
« Prev Post
Next post
Next Post »