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(); } }
nice example. But there is an issue. If my fragment is doing too much of background work the navigation closing is causing a delay. Any workaround on this ?
Yes, do the fragment transaction on onDrawerClosed()
i wish you have presented in more easier manner without copying from developer.android.com..
This requires API level 11, so it’s available for Android 3.0+ if i’m not mistaken.
Yes, the above example works 3.0+
How would you add icons to the navigation drawer? Also, how would you enable the webview to go back? Any help would be amazing.
YEs javatechig, it would be perfect 🙂
This is by far the best tutorial.
First ever Android sample I downloaded from web worked!! I’m new to Java and never had a success in running a demo app downloaded from web. Your’s is the first working sample of Android i found online. Thank you very much.
Thanks for reading.
It will work if you include support jar : http://developer.android.com/tools/support-library/index.html
Thanks for your reply.
Hey, lovely sample app. My only problem is each of the items in the menu opens the url in the browser (outside of the app) can you please advise.
which app or device are you testing on?
Hey, testing on os 4.2.2 but i saw the problem, there was no webclient view initiated. So i added the line below just before webView.loadUrl(url); in the WebViewFragment.java file
webView.setWebViewClient(new WebViewClient());
It is just an example of navigation drawer. You can fix such bugs
Hello, great job, i have one question, how to add ico for each menu side by side .
Answer please thanks
This is no more a android design pattern. Suggest to go with default android guidelines.
I love you!
How to get this will u pls heip me pls send the code for this
how to get this
Checkout this lib..
https://github.com/jfeinstein10/SlidingMenu
By default in android Navigation menu, you cannot move the action bar while menu is open. But you can achieve with the above github code.
what i do for getting
that exact screen shot in android
good job dude . but i want to make navigation drawer that let me like . for example if i clicked on android it open a webview (url)
i’m beginner in eclipse and i downloaded the source code , i want to open it but i dont know how to open it
Just start eclipse. In your workspace click File-> Import -> Existing android code into workspace.
I created one application and I used navigation drawer to navigate from one fragment to another. In that, if I navigate from one fragment to another and if again comeback to the same fragment. Its not getting resume. Its simply showing Unfortunately the app was closed. Can you tell me how to use onresume method properly in fragment???
can you paste the error message here ?
Hi, thanks for the awesome code, one question though, when starting the application it will show a blank page, could you modify the code so it will start with case 0 (home)?
Thank you!
Thanks for your suggestions. We will do the required changes.
hey how can i slide main layout toward the right (as per linkdin style). ?
Currently the example is developed for 4.0 and above
Add the following code on your onCreate to load fragment by default
// Creating a fragment object
WebViewFragment fragment = new WebViewFragment();
// Passing selected item information to fragment
Bundle data = new Bundle();
data.putString(“url”, getUrl(position));
fragment.setArguments(data);
// Getting reference to the FragmentManager
FragmentManager fragmentManager = getFragmentManager();
// Creating a fragment transaction
FragmentTransaction ft = fragmentManager.beginTransaction();
// Adding a fragment to the fragment transaction
ft.add(R.id.content_frame, fragment);
This doesn’t seem to work for me
It worked thanks, you did not include the last line for committing transaction
// Committing the transaction
ft.commit();
Thanks alot your tutorial really saved me
Oh. my bad. thanks for pointing it out
Hello please can u help me!! here u did loading fragments in same page ryt can u please tel me how to load activities to same layout like fragments with code example
An activity cannot be added inside another activity. It can be one top of other like card stack.
You should use fragment for such requirements.
Can you send me code to retrieve mysql data base content and display it as list view??
where to put code to be implemented in fragment any methods for it like onCreate() for activities…??
you can use onCreateView() method to initialize your ui.
Write your other logic inside onActivityCreated() method.
in my navigation drawer when i load one fragment other fragment will overlap the present what to do..please
help
use add() instead of replace() while adding fragment using fragment transaction .
It is easier with fragments. I don’t know why you want to do with activities. All fragments has similar life cycles as activities.
As fragments are recommended by Android, you must take a while to convert all your activities to fragments. Trust me it is not a big time task
i really apreciate your reply, thank you)
i decided to use activities because i couldn’t use map with markers in fragment…
You must read about fragment lifecycle and basics to get started with fragments.
http://developer.android.com/guide/components/fragments.html
did you add the code from the above featured comments. Will check soon and update the code.
yes sir , maybe i have not putted it on right place , can you please copy paste here your whole MainActivity.java code .
Updated code. have a check
Checkout latest code. Have updated the example code
You must set a WebViewClient instance. Checkout my WebView tutorial explains the same.
Same here, downloaded app code sample but menu won’t show on click and it couldn’t even load webpage. Using Android Studio 1.2.1.1
Will look into it soon.
how change slide menu right to left (from right side open & close too) ??plz help me
i change gravity of ListView from “start” to “right” and it open & close from right silde … how change ActionBar to right to left too(Titles & icons of items & menu icon set in right side of ActionBar) ??
Consider using this
Android-Lollipop-Navigation-Drawer
And do you have any tutorial to develop dynamic interfaces?
Sorry.. We currently we do not have any tutorial on dynamic interfaces.
Checkout the latest code here.
Android-Lollipop-Navigation-Drawer
what is drawer_list_item? Is it an empty xml file in layout??
How can I make sure the app closes when the user clicks the devices back button instead of the default fragment constantly refreshing?
You have to deal with Fragment backstack
Really nice navigation drawer example .
I have implemented navigation drawer in my application also . I have used cursor adapter which take data from Sqlite database . I can able to add content into listview of navigation drawer but upon click on each content I can execute related task but when second time when clicked on drawer toogle button previous content of drawer is getting lost why this is happening can anyone suggest me . I am not able to save drawer listview content please suggest what to do.