Site icon Treehouse Blog

How to Add a Navigation Drawer in Android

Android Navigation Drawer

Android now includes a component that makes it very easy to add a navigation drawer to an app that the user can slide in from the side. I first remember seeing this in the Facebook app in iOS, and I thought it was a pretty nifty mobile design pattern (though others some people strongly disagree). I will assume you are here because you think it is good for your app, though!

In Android this component is called the navigation drawer. The Android design guidelines have a nice section on when and how we should use the navigation drawer in an app. One of my favorite uses if for power-user features that might be confusing or overwhelming for infrequent users of the app, but that are nice to have easily accessible in a menu that can be pulled in from the side.

Android Studio now includes a project template for an app that includes a navigation drawer:

It is built on Fragments, which is a useful model to have, especially if you want a common navigation drawer across multiple screens. It might be a little more than needed for a simple app, so below I will walk through how to add a navigation drawer to an existing app from scratch. If your needs go beyond what we cover here, there is a lot of good information on the Android Developer site about how to create a Navigation Drawer.

Also check out: What is Android Development?

Open or Create a Project

If you care to follow along, clone or download my super simple starter app from GitHub: OS List. (The finished source is available at the end of this article.) All you need is an Activity, though. This app will target Android 4.0 and above, but the support library that brings us the Navigation Drawer makes this available on even older versions.

Your project may already contain the required dependency to use the Android support library, but if not, add the following line to the dependencies section in the build.gradle file for your app module:

compile 'com.android.support:appcompat-v7:21.0.3'

(You will probably want to use the latest version of the library.)

Update the Layout

The first thing we need to do is modify the layout for our Activity. We simply need to provide a regular layout for the Activity plus a separate layout for the navigation drawer, but both layouts are contained inside the same container: DrawerLayout.

In OS List, we have a simple RelativeLayout with a TextView and ImageView. To add a navigation drawer, we add a new root element of type android.support.v4.widget.DrawLayout.

<android.support.v4.widget.DrawerLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
</android.support.v4.widget.DrawerLayout>

Then we add a ListView for the side drawer view:

<ListView
    android:id="@+id/navList"
    android:layout_width="200dp"
    android:layout_height="match_parent"
    android:layout_gravity="left|start"
    android:background="#ffeeeeee"/>

The ListView (or whatever View we use as the side navigation drawer), should be no more than 320dp wide, so that it does not cover the entire Activity when it is out.

You can view the entire layout file here in the completed project on GitHub.

Set the List and Adapter in the Activity

Now that we have a ListView to work with, let’s set it in the Activity. In this example we will use a simple String array as our data set for the list, and an ArrayAdapter to adapt the data. (For more information about using lists and adapters, check out Android Lists and Adapters in the Treehouse library.)

First, let’s add two member variables to our Activity:

private ListView mDrawerList;
private ArrayAdapter<String> mAdapter;

Then we can set the ListView in onCreate():

mDrawerList = (ListView)findViewById(R.id.navList);

To add items and configure the list, let’s create a helper method that we can call inside onCreate():

private void addDrawerItems() {
    String[] osArray = { "Android", "iOS", "Windows", "OS X", "Linux" };
    mAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, osArray);
    mDrawerList.setAdapter(mAdapter);
}

At this point we have a working navigation drawer! Hooray!

We can perform an action when each item in the side navigation list is tapped just like we would for a regular ListView. Let’s set an OnItemClickListener and simply make a Toast about each item in the list:

mDrawerList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        Toast.makeText(MainActivity.this, "Time for an upgrade!", Toast.LENGTH_SHORT).show();
    }
});

This is the minimum basic code we need for a navigation drawer, but there is much more we can do!

Add a Toggle Switch in the Action Bar

Opinions may vary on this, but I personally prefer a hamburger menu or some kind of icon in the Action Bar that lets me know the navigation drawer is there. We can use the default icon provided by Android with a few more changes in our Activity. We can show it by adding two lines in our onCreate() method (though it won’t do anything yet):

 getSupportActionBar().setDisplayHomeAsUpEnabled(true);
 getSupportActionBar().setHomeButtonEnabled(true);

To get this to work correctly, we need to configure something called an ActionBarDrawerToggle.

Let’s start with a few new member variable for this new object. We need one for the toggle, one for the DrawerLayout we added to our layout, and a String that we will use to update the title in the Action Bar:

private ActionBarDrawerToggle mDrawerToggle;
private DrawerLayout mDrawerLayout;
private String mActivityTitle;

Before we forget, let’s set mDrawerLayout and mActivityTitle in onCreate():

mDrawerLayout = (DrawerLayout)findViewById(R.id.drawer_layout);
mActivityTitle = getTitle().toString();

Using a toggle requires two String resources, so let’s add those in strings.xml in the res/values directory before we proceed:

<string name="drawer_open">Open navigation drawer</string>
<string name="drawer_close">Close navigation drawer</string>

Okay! Now we can add a new helper method that we will call from onCreate() after the drawer items have been set up:

private void setupDrawer() {
}

Here is where we will initialize mDrawerToggle. Autocomplete is really helpful here; or just copy and paste from below. We want to create a new ActionBarDrawerToggle instance that uses the context, mDrawerLayout, and those two new string resources we added, and then we need to implement two methods: onDrawerOpened() and onDrawerClosed():

mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout,
        R.string.drawer_open, R.string.drawer_close) {

    /** Called when a drawer has settled in a completely open state. */
    public void onDrawerOpened(View drawerView) {
    }

    /** Called when a drawer has settled in a completely closed state. */
    public void onDrawerClosed(View view) {
    }
};

When the drawer is opened, we can set a new title for the Action Bar (if we want). We also want to invalidate the options menu in case it needs to be recreated with different options for when the navigation drawer is open:

public void onDrawerOpened(View drawerView) {
    super.onDrawerOpened(drawerView);
    getSupportActionBar().setTitle("Navigation!");
    invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu()
}

And then when it is closed we will do the opposite. Revert the title (which we stored in mActivityTitle) and again invalidate the options menu:

public void onDrawerClosed(View view) {
    super.onDrawerClosed(view);
    getSupportActionBar().setTitle(mActivityTitle);
    invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu()
}

At this point our toggle still won’t work. We need to add two more lines to enable the drawer indicator (the lovely hamburger menu) and then attach this new toggle object to our drawer layout. Add these two lines in setupDrawer() after mDrawerToggle is set:

mDrawerToggle.setDrawerIndicatorEnabled(true);
mDrawerLayout.setDrawerListener(mDrawerToggle);

Finally, we need to activate this in the onOptionsItemSelected() method. Add this block of code anywhere in the method:

if (mDrawerToggle.onOptionsItemSelected(item)) {
    return true;
}

To see the whole file check out MainActivity.java in the completed project on GitHub.

Keep Everything in Sync

Notice in the animated gif above that the icon isn’t quite in sync with the drawer. We need to call one more method in the onPostCreate() lifecycle method of our Activity. Inside onPostCreate(), call mDrawerToggle.syncState() to sync the indicator to match the current state of the navigation drawer:

@Override
protected void onPostCreate(Bundle savedInstanceState) {
    super.onPostCreate(savedInstanceState);
    mDrawerToggle.syncState();
}

The other scenario we need to plan for to keep things in sync is when the configuration of the Activity changes, like, for example, going from portrait to landscape or showing the soft keyboard on the screen. We do this in the Activity’s onConfigurationChanged() method, which you may need to add:

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    mDrawerToggle.onConfigurationChanged(newConfig);
}

Related Reading: Scheduling Time-Sensitive Tasks in Android with the AlarmManager

Next Steps

At this point we have a complete, working example of a navigation drawer that can be swiped in from the side or accessed via a button in the Action Bar. There is a lot more we can customize depending on our needs, of course, but this is a powerful tool that is now very easy to use thanks to the components added to the Android support library.

Look for courses, workshops, and other tips like this in the Android section of the Treehouse library, and check out the 7-day free trial. Happy coding!


Learn in-demand programming skills and become a certified Android Developer with the Treehouse Techdegree Program. Learn more and enroll today.
Exit mobile version