Part 4 – Playing with NavigationView

By -

Welcome to the fourth part of this tutorial series on “Android design support library”. To read overview of the series, refer to the serious announcement blog post.

A quick glimpse of all parts:

  • Part 1, we talked about Floating action button
  • Part 2 is about Snackbar
  • Part 3 is about Styling snackbar where we saw how to display different coloured Snackbar

In this part – NavigationView

At the time announcing material design, we didn’t have all the tools and components, rather we were dependent on the third-party libraries and tools, but with the release of android design support library, it becomes easier to implement Navigation drawer in our android applications, if you have implemented navigation drawer earlier then you would know how it was cumbersome task!

In short, Navigation view makes it far easier to create a navigation drawer then the previously documented example.

In this part, I will directly talk about NavigationView, which is another important and awesome component provided in android design support library.

NavigationView - Android design support library

How Navigation view works?

If you remember, earlier we were dependent on either ListView or LinearLayout, were defining a custom adapter for displaying Navigation drawer as per the need, but with this NavigationView, we just need to include in inside the same DrawerLayout, so point is earlier we were including ListView inside DrawerLayout and now we will include NavigationView inside DrawerLayout.

Two important parameters
Below are the two important parameters required to set up NavigationView, same as the navigation drawer in Inbox and Google play store applications.

  • app:menu – list of navigation drawer items, here we will just need to create a normal menu file for the required items.
  • app:headerLayout – which is header layout, like we display background image and profile picture with name and other details.
    <android.support.design.widget.NavigationView
        android:id="@+id/navigation_view"
        android:layout_height="match_parent"
        android:layout_width="wrap_content"
        android:layout_gravity="start"
        android:fitsSystemWindows="true"
        app:headerLayout="@layout/drawer_header"
        app:menu="@menu/drawer_view"/>

There are 2 ways to implement a navigation drawer, we will see both the ways.

  1. Design time, by preparing menu file with the items
  2. Run time, by adding items into the Navigation view programatically

Now, let’s get started!

1. Design time

Step 1: Create a menu for navigation drawer items

It’s same as creating a menu xml file (drawer_view.xml), just create a menu file under menu folder.

<menu xmlns:android="http://schemas.android.com/apk/res/android">

    <group android:checkableBehavior="single">
        <item
            android:id="@+id/nav_home"
            android:icon="@drawable/ic_drawer_home"
            android:title="@string/nav_home" />
        <item
            android:id="@+id/nav_about"
            android:icon="@drawable/ic_drawer_about"
            android:title="@string/nav_about" />
        <item
            android:id="@+id/nav_settings"
            android:icon="@drawable/ic_drawer_settings"
            android:title="@string/nav_settings" />

        <item
            android:id="@+id/navigation_subheader"
            android:title="@string/nav_sub_header">
            <menu>
                <item
                    android:id="@+id/navigation_sub_item_1"
                    android:icon="@drawable/ic_drawer_about"
                    android:title="@string/nav_sub_item_1" />
                <item
                    android:id="@+id/navigation_sub_item_2"
                    android:icon="@drawable/ic_drawer_home"
                    android:title="@string/nav_sub_item_2" />
            </menu>
        </item>
    </group>
</menu>

Checkable menu items
You can define the checkable behaviour for individual menu items using the android:checkable attribute in the element, or for an entire group with the android:checkableBehavior attribute in the element.

The android:checkableBehavior attribute accepts either:

  • single – Only one item from the group can be checked (radio buttons)
  • all – All items can be checked (checkboxes)
  • none – No items are checkable

Step 2: Create a header layout

Create a header layout (drawer_header.xml) in layout folder, include whatever views you want in header of navigation drawer.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="192dp"
    android:background="?attr/colorPrimaryDark"
    android:padding="16dp"
    android:theme="@style/ThemeOverlay.AppCompat.Dark"
    android:orientation="vertical"
    android:gravity="bottom">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Username"
        android:textAppearance="@style/TextAppearance.AppCompat.Body1"/>
</LinearLayout>

Step 3: Get NavigationView and include menu and header layout

Open activity_main.xml layout file and include NavigationView with including menu and header layout attributes.

<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/drawer_layout"
    android:layout_height="match_parent"
    android:layout_width="match_parent"
    android:fitsSystemWindows="true">

    <!-- Your content layout goes here -->

    <android.support.design.widget.NavigationView
        android:id="@+id/nav_view"
        android:layout_height="match_parent"
        android:layout_width="wrap_content"
        android:layout_gravity="start"
        android:fitsSystemWindows="true"
        app:headerLayout="@layout/nav_drawer_header"
        app:menu="@menu/nav_drawer_view"/>

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

Step 4: Initialize Navigation view in activity class

private NavigationView mNavigationView;
mNavigationView = (NavigationView) findViewById(R.id.navigation_view);

Step 5: Assign navigation drawer item selected listener

//setting up selected item listener
navigationView.setNavigationItemSelectedListener(
       new NavigationView.OnNavigationItemSelectedListener() {
              @Override
              public boolean onNavigationItemSelected(MenuItem menuItem) {
                        menuItem.setChecked(true);
                        mDrawerLayout.closeDrawers();
                        return true;
              }
       });

2. Creating Navigation view programmatically

There could be a scenario where you need to prepare a navigation view by adding items programmatically. We are adding items programmatically in our Google Developers Group android application, it’s yet to roll out the new version with design support library integration!

To add the item programatically, we can get a Menu object using getMenu() method of NavigationView and then we can add items into the navigation drawer using that Menu object.

final Menu menu = navigationView.getMenu();
for (int i = 1; i <= 3; i++) {
    menu.add("Runtime item "+ i);
}

Using SubMenu, we can add a subsection and items into it.

// adding a section and items into it
final SubMenu subMenu = menu.addSubMenu("SubMenu Title");
for (int i = 1; i <= 2; i++) {
    subMenu.add("SubMenu Item " + i);
}

As we have added items into the navigation drawer adapter, refresh the adapter using below code:

        for (int i = 0, count = mNavigationView.getChildCount(); i < count; i++) {
            final View child = mNavigationView.getChildAt(i);
            if (child != null && child instanceof ListView) {
                final ListView menuView = (ListView) child;
                final HeaderViewListAdapter adapter = (HeaderViewListAdapter) menuView.getAdapter();
                final BaseAdapter wrapped = (BaseAdapter) adapter.getWrappedAdapter();
                wrapped.notifyDataSetChanged();
            }
        }

Other Points:

  • If you want to listen to the navigation drawer open and close event then you can take our older ActionBarDrawerToggle but of V7 support library.
  • You should replace older action bar with Toolbar
            Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
            setSupportActionBar(toolbar);
    
            final ActionBar ab = getSupportActionBar();
            ab.setHomeAsUpIndicator(R.drawable.ic_menu);
            ab.setDisplayHomeAsUpEnabled(true);
         

    And use No action bar theme.

        <style name="AppTheme" parent="Base.Theme.DesignDemo">
        </style>
    
        <style name="Base.Theme.DesignDemo" parent="Theme.AppCompat.Light.NoActionBar">
            <item name="colorPrimary">#2196F3</item>
            <item name="colorPrimaryDark">#1976D2</item>
            <item name="colorAccent">#E040FB</item>
            <item name="android:windowBackground">@color/window_background</item>
        </style>
    
  • Handle menu icon click event
        @Override
        public boolean onOptionsItemSelected(MenuItem item) {
    
            int id = item.getItemId();
    
            switch (id) {
    
                case android.R.id.home:
                    mDrawerLayout.openDrawer(GravityCompat.START);
                    return true;
    
                case R.id.action_settings:
                    return true;
            }
    
            return super.onOptionsItemSelected(item);
        }
    
  • Handle back key press event, standard is to close the navigation drawer if it is open.
       @Override
        public void onBackPressed() {
            if (isNavDrawerOpen()) {
                closeNavDrawer();
            } else {
                super.onBackPressed();
            }
        }
    
        protected boolean isNavDrawerOpen() {
            return mDrawerLayout != null && mDrawerLayout.isDrawerOpen(GravityCompat.START);
        }
    
        protected void closeNavDrawer() {
            if (mDrawerLayout != null) {
                mDrawerLayout.closeDrawer(GravityCompat.START);
            }
        }
    

Open issue

  • As we discussed above, we include android:checkableBehavior="single" to mark a single item checked at a time, but it is not working for the sub section items. Yes, currently it’s only working for the first group menu items

Download source code

You can download a complete example from the design support library examples repository, bookmark this repository! I would be adding more examples and a complete demo (demo of all the design support library components) into this repository!

Wrapping up

This bring us to the end of this part. In this part, we have seen how we can prepare a NavigationView design time and adding sub-section. We have also seen adding items into the navigation view programmatically. As said if you want to listen to the navigation drawer open and close event then you can include ActionBarDrawerToggle too!

So far we have talked about Snackbar, Floating action button and NavigationView, total three awesome components of android design support library. In further parts, we will talk about CoordinatorLayout and behaviors, Floating label edit text, Tab layout, App bar layout and an amazing collapsing toolbar. See you in next part!

Paresh Mayani

Lazy android developer, exploring the horizon of android development since 7 years, currently working as a Technical Lead - Android at Simform Solutions, India. Former Application Architect at KarConnect. He is the Head/Organizer of Google Developers Group (GDG), Ahmedabad

Loading Facebook Comments ...
Loading Disqus Comments ...