Android – Creating a Navigation Drawer

android-navigation-drawerThe navigation drawer is a list “ListView” of options on the left edge of the screen. It is hidden most of the time, but is revealed when the user swipes a finger from the left edge of the screen or, the user touches the app icon in the action bar.

 

Objectives:

  • How to add a navigation drawer to you app?
  • How to populate the drawer list?
  • How to open the drawer by clicking on the app icon “top-left icon”?
  • How to handle click events?

Environment & Tools:

  • Android Developer Tools (ADT) (or Eclipse + ADT plugin)
  • AVD Nexus S Android 4.3 “emulator”
  • Min SDK 11

( 1 ) Create Android Application

  • File >> New >> Android Application
  • Enter App name: android-navigation-drawer
  • Pakcage: com.hmkcode.android
  • Keep other defualt selections, go Next  till you reach Finish

( 2 ) Create Drawer Layout

  • Use DrawerLayout as the main layout for your activity.
  • Add two views, one for the main view “when the drawer is hidden” and one for the drawer.
  • The main content view (FrameLayout)  must be the first child in the DrawerLayout because the XML order implies z-ordering and the drawer must be on top of the content.
  • res/layout/activity_main.xml
<android.support.v4.widget.DrawerLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <!-- The main content view -->
    <FrameLayout
        android:id="@+id/content_frame"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <!-- The navigation drawer -->
    <ListView android:id="@+id/left_drawer"
        android:layout_width="240dp"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:choiceMode="singleChoice"
        android:divider="#666"
        android:dividerHeight="1dp"
        android:background="#333"
        android:paddingLeft="15sp"
        android:paddingRight="15sp"
        />

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

( 3 ) Drawer List Item Layout

  • The list item layout is just a single TextView, but we did some styling such as padding, background color, text color and text size.
  • res/layout/drawer_listview_item.xml
<?xml version="1.0" encoding="utf-8"?>

<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@android:id/text1"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:textColor="#fff"
    android:textSize="20sp"
    android:gravity="center_vertical"
    android:paddingStart="14.5sp"
    android:paddingEnd="14.5sp"
    android:minHeight="35sp"
/>

( 4 ) Some Strings

  • We need to define string array for the drawer list.
  • res/values/strings.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>

    <string name="app_name">App</string>
    <string name="action_settings">Settings</string>
    <string name="hello_world">Hello world!</string>

    <string-array name="items">
        <item>Item 1</item>
        <item>Item 2</item>
        <item>Item 3</item>
        <item>Item 4</item>
        <item>Item 5</item>
        <item>Item 6</item>
    </string-array>

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

( 5 ) Activity Class

  • Get the list “array” of items to be added to the drawer list from strings.xml.
  • Get the reference to the ListView
  • Call ListView.setAdapter(ArrayAdapter).
  • res/com/hmkcode/android/MainActivity.java
package com.hmkcode.android;

import android.os.Bundle;
import android.app.Activity;
import android.widget.ArrayAdapter;
import android.widget.ListView;

public class MainActivity extends Activity {

	private String[] drawerListViewItems;
    private ListView drawerListView;

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

		// get list items from strings.xml
		drawerListViewItems = getResources().getStringArray(R.array.items);

		// get ListView defined in activity_main.xml
		drawerListView = (ListView) findViewById(R.id.left_drawer);

                // Set the adapter for the list view
		drawerListView.setAdapter(new ArrayAdapter<String>(this,
                R.layout.drawer_listview_item, drawerListViewItems));

	}

}
  • This code is enough to view the drawer by swiping from left to right.
  • We can add one more way to open and close the drawer by clicking on App icon “top-left icon”

( 6 ) Open & Close the Drawer With App Icon

  • Get reference to DrawerLayout define in activity_main.xml.
  • Declare ActionBarDrawerToggle
ActionBarDrawerToggle(Activity activity, DrawerLayout drawerLayout, int drawerImageRes, int openDrawerContentDescRes, int closeDrawerContentDescRes)
  • DrawerLayout.setDrawerListener(ActionBarDrawerToggle)
  • getActionBar().setDisplayHomeAsUpEnabled(true);
if you setDisplayHomeAsUpEnabled(true) an “back or up” arrow will be displayed
  • Override onConfigurationChanged
Call actionBarDrawerToggle.onConfigurationChanged(newConfig) passing the Configuration arugment
  • Override onOptionsItemSelected
onOptonsItemSelected method is called whenever an item in your action bar is selected and since App Icon is on the action bar this method will be called.
  • res/com/hmkcode/android/MainActivity.java
package com.hmkcode.android;

import android.os.Bundle;
import android.app.Activity;
import android.content.res.Configuration;
import android.support.v4.app.ActionBarDrawerToggle;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;

public class MainActivity extends Activity {

	private String[] drawerListViewItems;
    private DrawerLayout drawerLayout;
    private ListView drawerListView;
    private ActionBarDrawerToggle actionBarDrawerToggle;

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

		// get list items from strings.xml
		drawerListViewItems = getResources().getStringArray(R.array.items);
		// get ListView defined in activity_main.xml
		drawerListView = (ListView) findViewById(R.id.left_drawer);

        // Set the adapter for the list view
		drawerListView.setAdapter(new ArrayAdapter<String>(this,
                R.layout.drawer_listview_item, drawerListViewItems));

		// App Icon 
		drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);

		actionBarDrawerToggle = new ActionBarDrawerToggle(
                this,                  /* host Activity */
                drawerLayout,         /* DrawerLayout object */
                R.drawable.ic_drawer,  /* nav drawer icon to replace 'Up' caret */
                R.string.drawer_open,  /* "open drawer" description */
                R.string.drawer_close  /* "close drawer" description */
                );

        // Set actionBarDrawerToggle as the DrawerListener
        drawerLayout.setDrawerListener(actionBarDrawerToggle);

        getActionBar().setDisplayHomeAsUpEnabled(true); 

        // just styling option add shadow the right edge of the drawer
	drawerLayout.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START);

	}

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

	@Override
    public boolean onOptionsItemSelected(MenuItem item) {

         // call ActionBarDrawerToggle.onOptionsItemSelected(), if it returns true
        // then it has handled the app icon touch event
        if (actionBarDrawerToggle.onOptionsItemSelected(item)) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }

}

Show standard navigation drawer icon

You can find the standard icon here Download the Action Bar Icon Pack.

We already set the icon of the drawer when we created the ActionBarDrawerToggle. to display the icon, sync the ActionBarDrawerToggle state onPostCreate().

Add this to the activity class (MainActivity.java)

@Override
    protected void onPostCreate(Bundle savedInstanceState) {
        super.onPostCreate(savedInstanceState);
        // Sync the toggle state after onRestoreInstanceState has occurred.
         actionBarDrawerToggle.syncState();
    }

( 7 ) Handle Navigation Drawer “Items” Click Events

To receive click events in the navigation drawer’s list we need to do two things:

First:

inside onCreate() mthod call ListView.setOnItemClickListener(ListView.OnItemClickListener);

  • ListView = drawerListView
  • ListView.OnItemClickListener = DrawerItemClickListener “next in second step”
drawerListView.setOnItemClickListener(new DrawerItemClickListener());

Second:

  • We will implement ListView.OnItemClickListener in a private inner class “DrawerItemClickListener” and override onItemClick() method.
  • onItemClick() will simply show a Toast displaying the clicked item text e.g. “Item 1″ and then close the drawer.

Add this to the activity class MainActivity.java

private class DrawerItemClickListener implements ListView.OnItemClickListener {
	    @Override
	    public void onItemClick(AdapterView parent, View view, int position, long id) {
	    	Toast.makeText(MainActivity.this, ((TextView)view).getText(), Toast.LENGTH_LONG).show();
	    	drawerLayout.closeDrawer(drawerListView);

	    }
	}

Complete Code:

package com.hmkcode.android;

import android.os.Bundle;
import android.app.Activity;
import android.content.res.Configuration;
import android.support.v4.app.ActionBarDrawerToggle;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends Activity {

	private String[] drawerListViewItems;
    private DrawerLayout drawerLayout;
    private ListView drawerListView;
    private ActionBarDrawerToggle actionBarDrawerToggle;

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

		// get list items from strings.xml
		drawerListViewItems = getResources().getStringArray(R.array.items);
		// get ListView defined in activity_main.xml
		drawerListView = (ListView) findViewById(R.id.left_drawer);

        // Set the adapter for the list view
		drawerListView.setAdapter(new ArrayAdapter<String>(this,
                R.layout.drawer_listview_item, drawerListViewItems));

		// 2. App Icon 
		drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);

		// 2.1 create ActionBarDrawerToggle
		actionBarDrawerToggle = new ActionBarDrawerToggle(
                this,                  /* host Activity */
                drawerLayout,         /* DrawerLayout object */
                R.drawable.ic_drawer,  /* nav drawer icon to replace 'Up' caret */
                R.string.drawer_open,  /* "open drawer" description */
                R.string.drawer_close  /* "close drawer" description */
                );

        // 2.2 Set actionBarDrawerToggle as the DrawerListener
        drawerLayout.setDrawerListener(actionBarDrawerToggle);

        // 2.3 enable and show "up" arrow
        getActionBar().setDisplayHomeAsUpEnabled(true); 

        // just styling option
		drawerLayout.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START);

		drawerListView.setOnItemClickListener(new DrawerItemClickListener());
	}

	@Override
    protected void onPostCreate(Bundle savedInstanceState) {
        super.onPostCreate(savedInstanceState);
        // Sync the toggle state after onRestoreInstanceState has occurred.
         actionBarDrawerToggle.syncState();
    }

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

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {

		 // call ActionBarDrawerToggle.onOptionsItemSelected(), if it returns true
        // then it has handled the app icon touch event

		if (actionBarDrawerToggle.onOptionsItemSelected(item)) {
            return true;
        }
		return super.onOptionsItemSelected(item);
	}

	private class DrawerItemClickListener implements ListView.OnItemClickListener {
	    @Override
	    public void onItemClick(AdapterView parent, View view, int position, long id) {
	    	Toast.makeText(MainActivity.this, ((TextView)view).getText(), Toast.LENGTH_LONG).show();
	    	drawerLayout.closeDrawer(drawerListView);

	    }
	}
}

Source Code @ GitHub

Related posts from Android Tutorial

8 thoughts on “Android – Creating a Navigation Drawer

      1. Jeezes

        Found the answer! well at least for my problem. It was the contentView that wasn’t set as it should’ve been.

  1. Fernando

    I have a problem when placed another listview. The menu does not catch the click event
    you know what can be the problem?

  2. zheng xu

    I have a problem when encountering step 5 .
    drawerListViewItems = getResources().getStringArray(R.array.items);

    where my R.array.items have an error on array.

    how do i solve it?

    1. hani.hmk Post author

      Hi,

      Let me know more details about the problem so I can help.
      But, make sure you define the “items” array in the strings.xml

Comments are closed.