AndroidPub
Published in

AndroidPub

Ultimate Guide to Bottom Navigation on Android

In this tutorial, learn to add a Bottom Bar and manage Fragments with it.

Facebook iOS app TabBar

What is Bottom Navigation?

Bottom navigation bars make it easy to explore and switch between top-level views in a single tap. — Material Design spec

This helps developers opt for Bottom Navigation, instead of a Navigation Drawer.

YouTube app’s simplified navigation with Bottom Bar

When to use?

A Bottom Navigation is best used when you have three to five top-level navigation items of similar importance.

Until now, the default, go-to navigation solution is the Navigation Drawer. Would you agree?

  • simpler — lesser the options, easier to remember

A simpler way to look at it…

If all that seems too complex, then just keep the number of navigation screens in mind.

  • 3 to 5 screens — Bottom Navigation
  • 5 and above — Navigation Drawer

Getting Started

I must admit the Bottom Navigation looks pretty cool. I noticed Aurelien Hubert has a fancy Bottom Navigation library. So let’s use that for this tutorial.

dependencies {
//...
compile 'com.aurelhubert:ahbottomnavigation:2.0.4'
}

Adding Bottom Navigation to Layout

Make sure your parent layout is a CoordinatorLayout. This ensures the Bottom Navigation behaves correctly with Snackbar and FAB.

<android.support.design.widget.CoordinatorLayout
android:id="@+id/coordinator"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"/>
</android.support.design.widget.AppBarLayout><FrameLayout
android:id="@+id/frame"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
<com.aurelhubert.ahbottomnavigation.AHBottomNavigation
android:id="@+id/bottom_navigation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"/>
</android.support.design.widget.CoordinatorLayout>

Moving onto Java

Each Bottom Navigation bar item denotes a different color. For demonstration purposes, each item click will change the Fragment’s view color. But ideally, you’ll want to load a different Fragment for each item. I’ll tell you how to switch Fragments, a bit further into the article.

1. Create your Items

There are different constructors you can use to define your Bottom Navigation items.

AHBottomNavigationItem item1 = 
new AHBottomNavigationItem(R.string.bottomnav_title_0,
R.drawable.ic_map_24dp);

2. Add Bottom Navigation items

Once you’ve defined the number of items, its time to add them to the Bottom Navigation.

bottomNavigation.addItem(item1);

3. Set Listener

Finally, you need to listen to item clicks. So add the following to your Fragment.

bottomNavigation.setOnTabSelectedListener(new AHBottomNavigation.OnTabSelectedListener() {
@Override
public void onTabSelected(int position, boolean wasSelected) {
fragment.updateColor(Color.parseColor(colors[position]));
}
});
// Setting the very 1st item as home screen. bottomNavigation.setCurrentItem(0);

Styling Bottom Navigation

Off the bat, the library provides considerable styling options. But after recent updates, there has been a lot more.

ContextCompat.getColor(context, R.id.yourcolor);
private int fetchColor(@ColorRes int color) {
return ContextCompat.getColor(this, color);
}

Simple Theming

At the most basic level, the Bottom Navigation requires these attributes:

  1. Accent color — highlights active items
  2. Inactive color — (you guessed it!) color for inactive items
bottomNavigation.setDefaultBackgroundColor(Color.WHITE);
bottomNavigation.setAccentColor(fetchColor(R.color.yourAccentColor));
bottomNavigation.setInactiveColor(fetchColor(R.color.yourInactiveColor));
Bottom Navigation with basic styling

Color Ripple Effects

You can take styling a step further by using a color ripple.

Bottom Navigation with Color Ripple
//  Enables color Reveal effect
bottomNavigation.setColored(true);
// Colors for selected (active) and non-selected items (in color reveal mode).
bottomNavigation.setColoredModeColors(Color.WHITE,
fetchColor(R.color.bottomtab_item_resting));

Text Labels

Here’s what the Material Design documentation tells us. If Bottom Navigation has:

  • 4–5 items — display text for active icon only and hide for inactive views
Bottom Navigation as seen in Material Design docs

The Material Design guidelines aren’t always right

Whether you have 3 or 5 items in your Bottom Navigation, ALWAYS show text labels!

Buttons or links that don’t explain to you what they do. Instead, you have to click on them to find out — Mystery Meat Navigation.

I’m sure we’ve all been victims of this at some point at least. We click on a button assuming it to do something, only for it to do something else entirely!

bottomNavigation.setTitleState(AHBottomNavigation.TitleState.ALWAYS_SHOW);

Translucent Bottom Navigation

Translucent Bottom Navigation
<style name="MyTheme.TranslucentNavigation" parent="MyTheme">
<item name="android:windowTranslucentNavigation">true</item>
</style>
// ... 
<activity
android:name=".YourActivity"
android:theme="@style/MyTheme.TranslucentNavigation">
//...
bottomNavigation.setTranslucentNavigationEnabled(true);

Behaviors

The library allows on-scroll animation for the Bottom Navigation Bar. It also supports a Translucent Theme for the same. Let’s see how we can enable both.

Quick Return Animation

A View can scroll off-screen with the content and return when the user reverse scrolls. — Quick Return

Hide on scroll — Quick Return
bottomNavigation.setBehaviorTranslationEnabled(true);

Translucent Navigation with Quick Return

Now you might get ambitious and want to combine both. A translucent Bottom Navigation and Quick Return pattern.

Toolbar clipping with Translucent bar + quick return
<android.support.design.widget.CoordinatorLayout >
<android.support.design.widget.AppBarLayout>
<LinearLayout
android:orientation="vertical">
<View
android:layout_width="match_parent"
android:layout_height="
@dimen/statusBarSize" />
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"/>
</LinearLayout>
</android.support.design.widget.AppBarLayout><!-- Your Fragment or ViewPager layout here...
Don't attribute app:layout_behavior="@string/appbar_scrolling_view_behavior" -->
<com.aurelhubert.ahbottomnavigation.AHBottomNavigation
android:id="@+id/bottom_navigation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"/>
</android.support.design.widget.CoordinatorLayout>
Translucent bar with quick return

Notification Badge

This again is simple. For the sake of demonstration, I’ll show you by creating a dummy notification.

Show notification

Let’s say I want to show a notification count of 1, for the last item. We can use the library’s AHNotification class for this.

private void createFakeNotification() {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
AHNotification notification = new AHNotification.Builder()
.setText("1")
.setBackgroundColor(Color.YELLOW)
.setTextColor(Color.BLACK)
.build();
// Adding notification to last item.
bottomNavigation.setNotification(notification, bottomNavigation.getItemsCount() - 1);notificationVisible = true;
}
}, 1000);
}
Notification Badge in Bottom Bar’s third item

Removing the Notification Icon

In the above code snippet, I used a boolean notificationVisible. It tells us whether the notification badge is currently visible or not.

  1. check if notification is visible and remove it
bottomNavigation.setOnTabSelectedListener(new AHBottomNavigation.OnTabSelectedListener() {
@Override
public boolean onTabSelected(int position, boolean wasSelected) {

//TODO: update Fragment here
// remove notification badge
int lastItemPos = bottomNavigation.getItemsCount() - 1;
if (notificationVisible && position == lastItemPos)
bottomNavigation.setNotification(new AHNotification(), lastItemPos);
return true;
}
});
Dismissing notification badge

Managing Bottom Navigation with Fragments

It’s pretty obvious by now that each Bottom Bar’s item manages a Fragment.

Maintaining Fragments with ViewPager

Now that we’ve decided on using a ViewPager to handle our Fragments, we need to write an Adapter.

  1. FragmentStatePagerAdapter

Using a FragmentStatePagerAdapter is more useful when there are a large number of pages. It holds on to much less memory associated with each visited page.

Okay, our Bottom Navigation has three items, but it can go up to five. So considering the extreme scenario, we can have five resource-heavy Fragments. So you can do your app a favour and use a FragmentStatePagerAdapter.

Creating the ViewPager Adapter

There’s a ‘smart’ implementation of FragmentStatePagerAdapter that allows us to access already existing Fragments from the Adapter. So go ahead and grab it from this GitHub gist.

public class BottomBarAdapter extends SmartFragmentStatePagerAdapter {
private final List<Fragment> fragments = new ArrayList<>();

public BottomBarAdapter(FragmentManager fragmentManager) {
super(fragmentManager);
}
// Our custom method that populates this Adapter with Fragments
public void addFragments(Fragment fragment) {
fragments.add(fragment);
}

@Override
public Fragment getItem(int position) {
return fragments.get(position);
}

@Override
public int getCount() {
return fragments.size();
}
}

Disable swiping on ViewPager

The easiest way is to create a custom ViewPager. So let’s create a new class extending ViewPager. I call it NoSwipePager, for the lack of a better name.

public class NoSwipePager extends ViewPager {
private boolean enabled;

public NoSwipePager(Context context, AttributeSet attrs) {
super(context, attrs);
this.enabled = true;
}

@Override
public boolean onTouchEvent(MotionEvent event) {
if (this.enabled) {
return super.onTouchEvent(event);
}
return false;
}

@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
if (this.enabled) {
return super.onInterceptTouchEvent(event);
}
return false;
}

public void setPagingEnabled(boolean enabled) {
this.enabled = enabled;
}
}
viewPager.setPagingEnabled(false);

Connecting ViewPager with PagerAdapter

Let’s create a simple Fragment called DummyFragment. It accepts one argument “color”. Using a different color will tell us which Fragment instance is shown when we use the Bottom Navigation.

// init UI
viewPager.setPagingEnabled(false);
pagerAdapter = new BottomBarAdapter(getSupportFragmentManager());
Bundle bundle = new Bundle();
bundle.putInt("color", color);
DummyFragment fragment = new DummyFragment();
fragment.setArguments(bundle);
pagerAdapter.addFragments(fragment);
viewPager.setAdapter(pagerAdapter);

Handling Click Events

Hang in there, we’re almost done!

bottomNavigation.setOnTabSelectedListener(new AHBottomNavigation.OnTabSelectedListener() {
@Override
public boolean onTabSelected(int position, boolean wasSelected) {

if (!wasSelected)
viewPager.setCurrentItem(position);
return true;
}
});
Congratulations you’re finally done with this long article. Give yourself a pat on the back!

Output

Just to give you a visual on how all that code works, here’s a GIF of everything put together.

Where to, from here?

The Bottom Navigation is the newest entry in Material Design. It pushes us to rethink our navigation structures.

Other Options

  1. Bottom Navigation Bar by roughike
    Clearly its the more popular one. But this library seems to work just as fine, so there’s no cause for alarm.
  2. Official Bottom Navigation by Design Support Library
    However, it is very limited in options in terms of styling and customization.

Wrap Up

So what do you think about Bottom Navigation? It is very common in iOS but I’m excited to see how we’re going to use it in Android.

--

--

The (retired) Pub(lication) for Android & Tech, focused on Development

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store