In this article, we will see how to develop an Android application containing sidebar navigation drawer menu with icons and counter. Here count specifies, how many times the drawer menu item is selected by the user since the application is opened.
In order to display ActionBar in legacy Android versions, we are making use ActionBarCompat library ( V7 ) . For navigation drawer library, we are making use Android Support Library ( V4 ) .
This application is developed in Eclipse 4.2.0 with Android SDK ( 22.2.1 ) and ADT plugin ( 22.2.1 ).
Screenshot of this application is available towards the end of this article.
1. Create an Android application project with the given below details
- Application Name : NavigationDrawerLegacy
- Project Name : NavigationDrawerLegacy
- Package Name : in.wptrafficanalyzer.navigationdrawerlegacy
- Minimum Required SDK : API 8 : Android 2.2 ( Froyo )
- Target SDK : API 18 : Android 4.3
- Compile With : API 18 : Android 4.3
- Theme : Holo Light with Dark Action Bar
2. Adding Android Support Library ( V4 )
By default, Android support library (android-support-v4.jar ) is added by Eclipse IDE to the directory libs. If it is not added, we can do it manually by doing the following steps :
- Open Project Explorer by Clicking “Window -> Show View -> Project Explorer”
- Right click this project
- Then from popup menu, Click “Android Tools -> Add Support Library “
3. Adding ActionBarCompat Support Library ( V7 )
Please refer the article titled “Android – Setting up ActionBarCompat support library in Eclipse”
4. Link this project to ActionBarCompat library
5. Download and extract the icon images to the directory res/drawable-mdpi
6. Update the file res/values/strings.xml
<?xml version="1.0" encoding="utf-8"?> <resources> <string name="app_name">NavigationDrawerLegacy</string> <string name="action_settings">Settings</string> <string name="hello_world">Hello world!</string> <string name="hello">Hello</string> <dimen name="count">10dp</dimen> <string name="drawer_open">Open navigation drawer</string> <string name="drawer_close">Close navigation drawer</string> <string-array name="countries"> <item>India</item> <item>Pakistan</item> <item>Sri Lanka</item> <item>China</item> <item>Bangladesh</item> <item>Nepal</item> <item>Afghanistan</item> <item>North Korea</item> <item>South Korea</item> <item>Japan</item> </string-array> </resources>
7. Create a Shape drawable in the file res/drawable/counter_shape.xml
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" > <solid android:color="#EAEAEA"/> <corners android:bottomLeftRadius="20dp" android:topRightRadius="20dp" android:topLeftRadius="20dp" android:bottomRightRadius="20dp" /> </shape>
8. Create a Shape drawable in the file res/drawable/drawer_title_shape.xml
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" > <solid android:color="#EAEAEA"/> <corners android:bottomLeftRadius="0dp" android:topRightRadius="0dp" android:topLeftRadius="0dp" android:bottomRightRadius="0dp" /> </shape>
9. Create a layout for the navigation drawer listview for legacy Android Versions ( API Level < 11 ) in the file res/layout/drawer_layout.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="60dp" > <ImageView android:id="@+id/flag" android:layout_width="40dp" android:layout_height="40dp" android:paddingLeft="10dp" android:paddingTop="10dp" android:paddingRight="10dp" android:paddingBottom="10dp" android:layout_alignParentLeft="true" android:layout_centerVertical="true" android:contentDescription="@string/hello" /> <TextView android:id="@+id/country" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_toRightOf="@id/flag" android:layout_centerVertical="true" android:textSize="15sp" /> <TextView android:id="@+id/count" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginRight="@dimen/count" android:layout_alignParentRight="true" android:layout_centerVertical="true" android:gravity="center" android:padding="0dp" android:background="@drawable/counter_shape" android:textSize="15sp" /> </RelativeLayout>
10. Create a layout for the navigation drawer listview for Android Versions ( API Level >= 11 ) in the file res/layout-v11/drawer_layout.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:background="?android:attr/activatedBackgroundIndicator" android:layout_height="60dp" > <ImageView android:id="@+id/flag" android:layout_width="40dp" android:layout_height="40dp" android:paddingLeft="10dp" android:paddingTop="10dp" android:paddingRight="10dp" android:paddingBottom="10dp" android:layout_alignParentLeft="true" android:layout_centerVertical="true" android:contentDescription="@string/hello" /> <TextView android:id="@+id/country" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_toRightOf="@id/flag" android:layout_centerVertical="true" android:textSize="15sp" /> <TextView android:id="@+id/count" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginRight="@dimen/count" android:layout_alignParentRight="true" android:layout_centerVertical="true" android:gravity="center" android:padding="0dp" android:background="@drawable/counter_shape" android:textSize="15sp" /> </RelativeLayout>
11. Create a layout file namely res/layout/fragment_layout.xml for the fragment CountryFragment
<?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="match_parent" android:orientation="vertical" > <TextView android:id="@+id/tv_content" android:layout_width="fill_parent" android:layout_height="fill_parent" android:gravity="center" android:textSize="40sp" /> </LinearLayout>
12. Update the layout file res/layout/activity_main.xml to include navigation drawer in the MainActivity
<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 --> <LinearLayout android:id="@+id/drawer" android:layout_width="240dp" android:layout_height="match_parent" android:orientation="vertical" android:layout_gravity="start" > <TextView android:layout_width="match_parent" android:layout_height="50dp" android:gravity="center" android:textSize="20sp" android:text="Country" android:background="@drawable/drawer_title_shape" /> <ListView android:id="@+id/drawer_list" android:layout_width="match_parent" android:layout_height="match_parent" android:choiceMode="singleChoice" android:divider="@android:color/darker_gray" android:dividerHeight="0.1dp" android:textColor="@android:color/white" android:background="#fff" /> </LinearLayout> </android.support.v4.widget.DrawerLayout>
13. Create a fragment class namely CountryFragment in the file src/in/wptrafficanalyzer/navigationdrawerlegacy/CountryFragment.java
package in.wptrafficanalyzer.navigationdrawerlegacy; import android.os.Bundle; import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; public class CountryFragment extends Fragment{ @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Retrieving the currently selected item number int position = getArguments().getInt("position"); // List of rivers String[] countries = getResources().getStringArray(R.array.countries); // Creating view correspoding to the fragment View v = inflater.inflate(R.layout.fragment_layout, container, false); // Getting reference to the TextView of the Fragment TextView tv = (TextView) v.findViewById(R.id.tv_content); // Setting currently selected river name in the TextView tv.setText(countries[position]); return v; } }
14. Update the file src/in/wptrafficanalyzer/navigationdrawerlegacy/MainActivity.java
package in.wptrafficanalyzer.navigationdrawerlegacy; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import android.os.Bundle; import android.support.v4.app.ActionBarDrawerToggle; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentTransaction; import android.support.v4.widget.DrawerLayout; import android.support.v7.app.ActionBarActivity; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.LinearLayout; import android.widget.ListView; import android.widget.SimpleAdapter; import android.widget.Toast; public class MainActivity extends ActionBarActivity { int mPosition = -1; String mTitle = ""; // Array of strings storing country names String[] mCountries ; // Array of integers points to images stored in /res/drawable-ldpi/ int[] mFlags = new int[]{ R.drawable.india, R.drawable.pakistan, R.drawable.srilanka, R.drawable.china, R.drawable.bangladesh, R.drawable.nepal, R.drawable.afghanistan, R.drawable.nkorea, R.drawable.skorea, R.drawable.japan }; // Array of strings to initial counts String[] mCount = new String[]{ "", "", "", "", "", "", "", "", "", "" }; private DrawerLayout mDrawerLayout; private ListView mDrawerList; private ActionBarDrawerToggle mDrawerToggle; private LinearLayout mDrawer ; private List<HashMap<String,String>> mList ; private SimpleAdapter mAdapter; final private String COUNTRY = "country"; final private String FLAG = "flag"; final private String COUNT = "count"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // Getting an array of country names mCountries = getResources().getStringArray(R.array.countries); // Title of the activity mTitle = (String)getTitle(); // Getting a reference to the drawer listview mDrawerList = (ListView) findViewById(R.id.drawer_list); // Getting a reference to the sidebar drawer ( Title + ListView ) mDrawer = ( LinearLayout) findViewById(R.id.drawer); // Each row in the list stores country name, count and flag mList = new ArrayList<HashMap<String,String>>(); for(int i=0;i<10;i++){ HashMap<String, String> hm = new HashMap<String,String>(); hm.put(COUNTRY, mCountries[i]); hm.put(COUNT, mCount[i]); hm.put(FLAG, Integer.toString(mFlags[i]) ); mList.add(hm); } // Keys used in Hashmap String[] from = { FLAG,COUNTRY,COUNT }; // Ids of views in listview_layout int[] to = { R.id.flag , R.id.country , R.id.count}; // Instantiating an adapter to store each items // R.layout.drawer_layout defines the layout of each item mAdapter = new SimpleAdapter(this, mList, R.layout.drawer_layout, from, to); // Getting reference to DrawerLayout mDrawerLayout = (DrawerLayout)findViewById(R.id.drawer_layout); // Creating a ToggleButton for NavigationDrawer with drawer event listener 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) { highlightSelectedCountry(); supportInvalidateOptionsMenu(); } /** Called when a drawer is opened */ public void onDrawerOpened(View drawerView) { getSupportActionBar().setTitle("Select a Country"); supportInvalidateOptionsMenu(); } }; // Setting event listener for the drawer mDrawerLayout.setDrawerListener(mDrawerToggle); // ItemClick event handler for the drawer items mDrawerList.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> arg0, View arg1, int position, long arg3) { // Increment hit count of the drawer list item incrementHitCount(position); if(position < 5) { // Show fragment for countries : 0 to 4 showFragment(position); }else{ // Show message box for countries : 5 to 9 Toast.makeText(getApplicationContext(), mCountries[position], Toast.LENGTH_LONG).show(); } // Closing the drawer mDrawerLayout.closeDrawer(mDrawer); } }); // Enabling Up navigation getSupportActionBar().setDisplayHomeAsUpEnabled(true); getSupportActionBar().setDisplayShowHomeEnabled(true); // Setting the adapter to the listView mDrawerList.setAdapter(mAdapter); } @Override protected void onPostCreate(Bundle savedInstanceState) { super.onPostCreate(savedInstanceState); mDrawerToggle.syncState(); } @Override public boolean onOptionsItemSelected(MenuItem item) { if (mDrawerToggle.onOptionsItemSelected(item)) { return true; } return super.onOptionsItemSelected(item); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } public void incrementHitCount(int position){ HashMap<String, String> item = mList.get(position); String count = item.get(COUNT); item.remove(COUNT); if(count.equals("")){ count = " 1 "; }else{ int cnt = Integer.parseInt(count.trim()); cnt ++; count = " " + cnt + " "; } item.put(COUNT, count); mAdapter.notifyDataSetChanged(); } public void showFragment(int position){ //Currently selected country mTitle = mCountries[position]; // Creating a fragment object CountryFragment cFragment = new CountryFragment(); // Creating a Bundle object Bundle data = new Bundle(); // Setting the index of the currently selected item of mDrawerList data.putInt("position", position); // Setting the position to the fragment cFragment.setArguments(data); // Getting reference to the FragmentManager FragmentManager fragmentManager = getSupportFragmentManager(); // Creating a fragment transaction FragmentTransaction ft = fragmentManager.beginTransaction(); // Adding a fragment to the fragment transaction ft.replace(R.id.content_frame, cFragment); // Committing the transaction ft.commit(); } // Highlight the selected country : 0 to 4 public void highlightSelectedCountry(){ int selectedItem = mDrawerList.getCheckedItemPosition(); if(selectedItem > 4) mDrawerList.setItemChecked(mPosition, true); else mPosition = selectedItem; if(mPosition!=-1) getSupportActionBar().setTitle(mCountries[mPosition]); } }
15. Update the file AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="in.wptrafficanalyzer.navigationdrawerlegacy" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="18" /> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/Theme.AppCompat.Light" > <activity android:name="in.wptrafficanalyzer.navigationdrawerlegacy.MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
16. Screenshot of the application
17. Download Source Code


I am George Mathew, working as software architect and Android app developer at wptrafficanalyzer.in
You can hire me on hourly basis or on project basis for Android applications development.
For hiring me, please mail your requirements to info@wptrafficanalyzer.in.
My other blogs
store4js.blogspot.com
I have problems when i want to produce this tuto for api 10 is it compatible with api 10 for android 2.3.3 thanks
Yah it is, i managed to use this tutorial targeting SDK 18 (4.3) and minimum SDK 8(Froyo, 2.2) but i was testing in my real device which runs 2.3, i also believe i can also go lower than that, Eclair(2.0).
Thanks! I have a doubt if I want to change the blue background in a selected item of the drawer, What I have to do?
And if I want to have a fragment that start with the app instead of empty screen… what I have to do?
Put this
if (savedInstanceState == null) {
// on first time display view for first nav item
showFragment(0);
}
immediately after this method:
@Override
public void onItemClick(AdapterView arg0, View arg1, int position,
long arg3) {
// Increment hit count of the drawer list item
incrementHitCount(position);
if(position < 5) { // Show fragment for countries : 0 to 4
showFragment(position);
}else{ // Show message box for countries : 5 to 9
Toast.makeText(getApplicationContext(), mCountries[position], Toast.LENGTH_LONG).show();
}
// Closing the drawer
mDrawerLayout.closeDrawer(mDrawer);
}
});
"0" will be your fist item in the list but you can change to second item which will be "2". Hope that helps.
Thank you very much, I did it and works.
Cool!
Hi, when i swipe from the edge of the screen the DrawerLayout will get stuck. It seems you have this problem in your solution:
Any ideias whats going on? Thanks
Can the drawerlayout displace the content of the main view rather than just overlaying it?
Thank u veryyy much..itssss osmmmmm
realy nice tutorial for api 8 and higher. thx author!
Hi George,
This tutorial helped me a lot, its perfect, i even managed to make my list items navigate to their desired Fragments/Activities/Pages/Screens when clicked/pressed by creating separate Fragments with their layouts and linking per each list item. Instead of using one Fragment. Thanks a lot
How can I change the image size of the first item on the menu?
Hey Carlos. You just need to behave like with usual listview. Just make new adapter which extends from BaseAdapter for example, and in a getView method make a check for first row. For example
class YourListAdapter extends BaseAdapter {
// generated metods and your code here
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = getLayoutInflater();
View row = inflater.inflate(R.layout.your_custom_row, parent, false);
ImageView i1=(ImageView)row.findViewById(R.id.img);
if(position == 0){
image.setLayoutParams(
new LinearLayout.LayoutParams(
newWidth,
newHeight));
}
return row;
}
}
Didn’t tried this code but think it’s ok. Feel free to contect me if you have some problems.
Hi,
I loved ur example. However i find my app crashing on device 4.0 and above when using appcompat action bar.
with NPE at
02-19 15:05:05.225: E/AndroidRuntime(796): at android.support.v7.app.ActionBarImplICS.setDisplayShowHomeEnabled(ActionBarImplICS.java:156)
also if i change it to setHomeButtonEnabled(true);
Am i missing something as app works fine below 3.0 but crashes on 4.0 above.
Help !!!
Thanks
Great Tutorial.
Was using the slidingmenu from jfeinstein for some time and started searching for this navigation drawer which uses support library from net but nothing seems to work for lower version.
yours where pretty neat and works.
Thanks.
Thank you for this tutorial. I want to have sub item in string-array, example: Europe with parts : east, north, west, south. Please help me
how can i change the drawer tittle from country?
appreciated thank you very much
Hi,
Thanks for your nice example. But I got some errors when I imported your project into my workspace.
Error saying:
The method replace(int, Fragment) in the type FragmentTransaction is not applicable for the arguments (int, CountryFragment)
I did below procedure.
1) imported your project
2) imported android-support-v7-appcompat into same workspace.
3) right click on navigation project -> properties->android-> add library appcomat
4)already there is v4 support library in lib folder of project
5) If i am not wrong then I guess there is v4 support library available in appcompat(v7) and v4 available in lib folder of navigation project. so is there any mismatch happening? please help me.
6) I tried to delete from one of project clean but no use. still giving error.
Thanks
It is not recognising Fragment class. when i deleted v4 library ther error gone but then it is not recognising replace method.
How can I change the itam name at run time.
Suppose you click on India. It should be change to Bharat after clicking on it.
And same on click Bharat it Should be change to India.
Replacement should be run time.
Hello
Nice tutorial
Can you show how to put section header to the listview to distinguish between the items Mr Mathew ?
Thanks alot…u mean alot to me…god bless
Can you please extend the code to have a collapsible list. Like World has 7 continents and they have different countries.
Thanks,
Namrata
how to put a expandable list in navigation drawer!!!
How to add expandable slider menu in navigation drawer?
I was in urgent need of above mentioned code
How to add expandable slider menu in navigation drawer?
I want to have sub item in string-array, example: Europe with parts : east, north, west, south. Please help me
I was in urgent need of above mentioned code
how to add list view in CountryFragment.java
hi sir,i want to implment this tutorial for right-to-left drawer,but can only implemented drawer layout from right-to-left slide,but i can not implementing navigation drawer toggole icon positon from left side to-right-side,how i can change drawer toggle icon from left to rigt ?it is possilbe?
Hie sir, I am getting an error at Line 100 in MainActivity.java, as “The constructor ActionBarDrawerToggle(MainActivity, DrawerLayout, int, int, int) is undefined”.. can u help me please
please cheek your email
Thanks for Excellent article. But I have one doubt, Can we develop the same Navigation Drawer or Like menu without V4/V7 ?. Any guide would be helpful especially in Xamarin Studio using C#
hello… how can an item selected remain highlighted unless other one is selected… thanks
i want to change textcolor in list view, i have change in activity_main.xml like this :
but the textcolor still same (can not changing)
Thanks a lot!
Really appreciate it.
How to remove that green highlighting when items are clicked?