1. Introduction
Android navigation drawer is a one of the most common used design pattern that displays the app’s main navigation links on the left side of the screen. It is not visible by default, and shown when swiped from left to right or by clicking the navigation menu icon from ActionBar.
The following example explains, how to implement a navigation drawer using Android Support Library DrawerLayout
API.
Navigation drawer is an overlay panel, that is replaced with the legacy application dashboard screen or menu. Now we don’t need to create a dedicated activity for showing all application options. You can simply it further by just using navigation drawer.
Before you decide to use a navigation drawer in your app, you should understand the use cases and design principles defined in the Navigation Drawer design guide. It is not an general replacement for top-level menu navigation.
Follow official Android on design guidelines follow for more information.
The following section of this tutorial, describes step by step approach to Implement a navigation drawer using the DrawerLayout APIs available in the Android Support Library. Some of the steps includes
- Create drawer layout
- Initialize navigation drawer layout
- Handle navigation drawer click
- Update content based on selection
4. Creating a Drawer Layout
For creating a navigation drawer, first we need to declare the drawer layout in your main activity where you want to show the navigation drawer. Add android.support.v4.widget.DrawerLayout
as root view of activity layout.
A DrawerLayout can have the layout for list to be shown inside navigation drawer and layout for main content view. In this example, the DrawerLayout contains two child views; one FrameLayout for main content, and a ListView for the navigation drawer. The FrameLayout is used to hold the child view’s populated by a Fragment at runtime.
<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 list--> <ListView android:id="@+id/drawer_list" android:layout_width="240dp" android:layout_height="match_parent" android:layout_gravity="start" android:background="#111" android:choiceMode="singleChoice" android:divider="@android:color/transparent" android:dividerHeight="0dp" /> </android.support.v4.widget.DrawerLayout>
Key Notes:
- The main content view is used as first child in the DrawerLayout. The XML order implies z-ordering and the drawer must be on top of the content.
- The main content view is set to match the parent view’s width and height, because it represents the entire UI when the navigation drawer is hidden.
- The width of drawer view is specified in dp (density independent pixels) units and the height matches the parent view. The drawer width should be no more than 320dp so the user can always see a portion of the main content.
5. Initialize the Drawer List
Now, first initialize the navigation drawer’s list of items. As here the navigation drawer consists a ListView, so the list can be populated by an Adapter.
items = getResources().getStringArray(R.array.menus); /* Getting reference to the DrawerLayout */ mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout); mDrawerList = (ListView) findViewById(R.id.drawer_list); /* Creating an ArrayAdapter to add items to mDrawerList */ ArrayAdapter adapter = new ArrayAdapter(this, R.layout.drawer_list_item, items); /* Setting the adapter to mDrawerList */ mDrawerList.setAdapter(adapter);
When the user selects an item in the drawer’s list, the system calls onItemClick() on the OnItemClickListener given to setOnItemClickListener(). In this example, selecting each item in the list inserts a different Fragment into the main content view FrameLayout.
// Setting item click listener to mDrawerList mDrawerList.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { selectedPosition = position; //Replace fragment content updateFragment(); mDrawerLayout.closeDrawer(mDrawerList); } });
Notice that in the above example we are using updateFragment() method that takes responsibility to update the content based on navigation drawer menu click. For the sake of simplicity, example loads the same WebView with different url. Add the following method to your activity.
public void updateFragment() { FragmentManager fragmentManager = getFragmentManager(); WebViewFragment rFragment = new WebViewFragment(); // Passing selected item information to fragment Bundle data = new Bundle(); data.putString("title", items[selectedPosition]); data.putString("url", getUrl()); rFragment.setArguments(data); //Replace fragment FragmentTransaction ft = fragmentManager.beginTransaction(); ft.replace(R.id.content_frame, rFragment); ft.commit(); }
7. Handle Drawer Open and Close Events
We can also listen to the drawer open and close event. To listen for drawer open and close events, we can extend the ActionBarDrawerToggle class. The ActionBarDrawerToggle implements DrawerLayout.DrawerListener.
/* Getting reference to the ActionBarDrawerToggle */ mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, R.drawable.ic_drawer, R.string.drawer_open, R.string.drawer_close) { /* Called when drawer is closed */ public void onDrawerClosed(View view) { //Put your code here } /* Called when a drawer is opened */ public void onDrawerOpened(View drawerView) { //Put your code here } }; /* Setting DrawerToggle on DrawerLayout */ mDrawerLayout.setDrawerListener(mDrawerToggle);
8. Download Complete Source
Download Source Code on Github
MainActivity.java
import android.annotation.SuppressLint; import android.app.Activity; import android.app.FragmentManager; import android.app.FragmentTransaction; import android.os.Bundle; import android.support.v4.app.ActionBarDrawerToggle; import android.support.v4.widget.DrawerLayout; import android.view.View; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.ArrayAdapter; import android.widget.ListView; public class MainActivity extends Activity { private DrawerLayout mDrawerLayout; private ListView mDrawerList; private ActionBarDrawerToggle mDrawerToggle; private String mTitle = "Navigation Drawer"; private String[] items; private int selectedPosition; @SuppressLint("NewApi") @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); getActionBar().setTitle(mTitle); items = getResources().getStringArray(R.array.menus); // Getting reference to the DrawerLayout mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout); mDrawerList = (ListView) findViewById(R.id.drawer_list); /* Creating an ArrayAdapter to add items to mDrawerList */ ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, R.layout.drawer_list_item, items); mDrawerList.setAdapter(adapter); mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, R.drawable.ic_drawer, R.string.drawer_open, R.string.drawer_close) { /* Called when drawer is closed */ public void onDrawerClosed(View view) { //Put your code here } /* Called when a drawer is opened */ public void onDrawerOpened(View drawerView) { //Put your code here } }; mDrawerLayout.setDrawerListener(mDrawerToggle); // Enabling Home button getActionBar().setHomeButtonEnabled(true); getActionBar().setDisplayHomeAsUpEnabled(true); // Setting item click listener for the listview mDrawerList mDrawerList.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { selectedPosition = position; /* Replace fragment content */ updateFragment(); /* Closing the drawer */ mDrawerLayout.closeDrawer(mDrawerList); } }); /* Setting default fragment */ selectedPosition = 0; updateFragment(); } public void updateFragment() { /* Getting reference to the FragmentManager */ FragmentManager fragmentManager = getFragmentManager(); /* Creating fragment instance */ WebViewFragment rFragment = new WebViewFragment(); /* Passing selected item information to fragment */ Bundle data = new Bundle(); data.putString("title", items[selectedPosition]); data.putString("url", getUrl()); rFragment.setArguments(data); /* Replace fragment */ FragmentTransaction ft = fragmentManager.beginTransaction(); ft.replace(R.id.content_frame, rFragment); ft.commit(); } protected String getUrl() { StringBuffer url = new StringBuffer("http://stacktips.com"); if (selectedPosition > 0) { url.append("/topics/" + items[selectedPosition].toLowerCase()); } return url.toString(); } @Override protected void onPostCreate(Bundle savedInstanceState) { super.onPostCreate(savedInstanceState); mDrawerToggle.syncState(); } }