Android.Basics – Adding a Bottom Navigation View

Changing my pace of steady Xamarin content to go to my roots of native mobile development. This time, we’ll look at implementing the latest control provided by Google and Material Design – The BottomNavigationView.

Resources

Aren’t These Just Tabs?

I mean… yeah, but… it’s new and cool! Google finally realized that stretching to the top of the app can be annoying.
Screen Shot 2017-06-27 at 5.56.48 PM.png

This new control is also a little different from the TabLayout we all know in love from Material Design and Android development in that it is limited to 5 maximum tab items and does not support scrolling. It’s meant to act as top level or sibling level navigation as long as all items are of equal importance in the context of the application/current view. It is also nice to give some variety to our applications navigation scheme; larger apps with many tabbed views can become overwhelming, so tossing something new is relieving to our users.

Code

There are 3 major components to setting up a view with a BottomNavigationView.

  1. First, we need to create a menu resource for our navigation items.
  2. Then we need to create, style, and set up our BottomNavigationView in our layout.
  3. Lastly, add listeners for when an item is selected in our BottomNavigationView and make sure it fits the experience expectation defined in Material Design.

Create a Menu

In our example, we will be building an application for viewing adoptable puppies. Each navigation item will be a different set of these puppies by categorizing them. Let’s create a menu for “all”, “big”, “small”, “trained”, and “active” as categories for our puppies:

res/menu/bottom_bar_menu.xml

<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:id="@+id/all_puppies"         android:title="@string/action_all"         android:icon="@drawable/ic_home_white_24dp" />

    <item android:id="@+id/big_puppies"         android:title="@string/action_big"         android:icon="@drawable/ic_dog_white_24dp" />

    <item android:id="@+id/small_puppies"         android:title="@string/action_small"         android:icon="@drawable/ic_small_dog_white_24dp" />

    <item android:id="@+id/trained_puppies"         android:title="@string/action_trained"         android:icon="@drawable/ic_trained_white_24dp" />

    <item android:id="@+id/active_puppies"         android:title="@string/action_active"         android:icon="@drawable/ic_active_white_24dp" />
</menu>

With our menu, we can create our layout.

Updating the Layout

In our example, we are moving from a TabLayout with a ViewPager. However, the Material Design documentation for the BottomNavigationView states that it should NOT be used with side-swiping actions such as a ViewPager. Let’s replace that ViewPager with a FrameLayout that will be used to swap our active Fragment and also remove the TabLayout that is being replaced by the BottomNavigationView:

res/layout/activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout 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/main_content"     android:layout_width="match_parent"     android:layout_height="match_parent"     android:fitsSystemWindows="true"     tools:context="com.suavepirate.bottomnavigationpuppies.activities.MainActivity">

    <android.support.design.widget.AppBarLayout         android:id="@+id/appbar"         android:layout_width="match_parent"         android:layout_height="wrap_content"         android:paddingTop="@dimen/appbar_padding_top"         android:theme="@style/AppTheme.AppBarOverlay">

        <android.support.v7.widget.Toolbar             android:id="@+id/toolbar"             android:layout_width="match_parent"             android:layout_height="?attr/actionBarSize"             android:background="?attr/colorPrimary"             app:layout_scrollFlags="scroll|enterAlways"             app:popupTheme="@style/AppTheme.PopupOverlay">

        </android.support.v7.widget.Toolbar>
    </android.support.design.widget.AppBarLayout>

<FrameLayout     android:id="@+id/container"     android:layout_width="match_parent"     android:layout_height="match_parent"     app:layout_behavior="@string/appbar_scrolling_view_behavior" ></FrameLayout>
<android.support.design.widget.BottomNavigationView     android:id="@+id/bottombar"     android:layout_width="match_parent"     android:layout_height="56dp"     android:layout_gravity="bottom|fill_horizontal|start"     app:menu="@menu/bottom_bar_menu"     android:background="@android:color/white"     app:elevation="8dp"/>
</android.support.design.widget.CoordinatorLayout>

It’s important to layout the BottomNavigationView at the bottom of the page as well as give it a solid background and elevation. Also, notice how we apply our menu we created to the view by setting app:menu="@menu/bottom_bar_men".

With our layout set, let’s wire up listeners to update the current Fragment based on the selected navigation item.

Setting Up Listeners

In our MainActivity.java we can implement the BottomNavigationView.OnNavigationItemSelectedListener interface and override the onNavigationItemSelected method:

MainActivity.java

// imports

public class MainActivity extends AppCompatActivity implements BottomNavigationView.OnNavigationItemSelectedListener {
    private PageAdapter mSectionsPagerAdapter;
    private FrameLayout mContainer;
    private BottomNavigationView mBottomBar;

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

        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        // Create the adapter that will return a fragment for each of puppy types
        mSectionsPagerAdapter = new PageAdapter(getSupportFragmentManager(), this);

        // Set up the ViewPager with the sections adapter.
        mContainer = (FrameLayout) findViewById(R.id.container);

        // set up the first Fragment
        FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
        ft.add(R.id.container, mSectionsPagerAdapter.getItem(0), "CURRENT_PAGE");
        ft.commit();

        // set up the bottom bar and listener
        mBottomBar = (BottomNavigationView)findViewById(R.id.bottombar);
        mBottomBar.setOnNavigationItemSelectedListener(this);

    }

    // Handles when an item is selected to update the fragment container
    @Override
    public boolean onNavigationItemSelected(@NonNull MenuItem item) {
        FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
        ft.setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_out);

        switch(item.getItemId()){
            case R.id.all_puppies: ft.replace(R.id.container, mSectionsPagerAdapter.getItem(0));
                break;
            case R.id.big_puppies: ft.replace(R.id.container, mSectionsPagerAdapter.getItem(1));
                break;
            case R.id.small_puppies: ft.replace(R.id.container, mSectionsPagerAdapter.getItem(2));
                break;
            case R.id.trained_puppies: ft.replace(R.id.container, mSectionsPagerAdapter.getItem(3));
                break;
            case R.id.active_puppies: ft.replace(R.id.container, mSectionsPagerAdapter.getItem(4));
                break;
        }
        ft.commit();
        return true;
    }
}

Now with all of this, we are able to switch the current Fragment with a fade in and out animation when the selected navigation item is updated. That means our BottomNavigationView is implemented and ready to go!

Screenshot_1497932698

If you like what you see, don’t forget to follow me on twitter @Suave_Pirate, check out my GitHub, and subscribe to my blog to learn more mobile developer tips and tricks!

Interested in sponsoring developer content? Message @Suave_Pirate on twitter for details.

3 thoughts on “Android.Basics – Adding a Bottom Navigation View”

    1. Sorry this post isn’t about Xamarin. Xamarin.Forms doesn’t support the version of the Android Support Design Library that has the BottomNavigationView yet. You can use a wrapper of Roughikes BottomBar library with a custom renderer. I have an example of that coming soon on my github.

      Like

Leave a comment