You might have noticed that lot of android applications introduced a sliding panel menu to navigate between major modules of the application. Previously this kind of UI was done using some third party libraries where a list view and some swiping gestures used to achieve this. But now android itself officially introduced sliding panel menu by introducing a newer concept called Navigation Drawer.
Most of the time Sliding Menu (Navigation Drawer) will be hidden and can be shown by swiping the screen from left edge to right or tapping the app icon on the action bar.
You might have heard of android Material Design which was introduced in Android Lollipop version. In Material Design lot of new things were introduced like Material Theme, new widgets, custom shadows, vector drawables and custom animations. If you haven’t working on Material Design yet, this article will give you a good start.
For Icons you can download it from here. You will get all sizes of icon here, that you can use in your project.
Go through the below links which give you much knowledge over Material Design :
In this tutorial, we are going to learn how to use navigation drawer to add a sliding menu to your application using material design.
Before starting you can go through my ToolBar Tutorial article for Color Schemes and styles for Material Design.
1. Create a new project in Eclipse by navigating to File ⇒ New Android ⇒ Application Project and fill required details. (I kept my main activity name as MainActivity.java).
2. Open your your AndroidManifest.xml file and set TargetSDK to 21 or 22 according to Lollipop and I had added two more activities because i am using three activities.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.android_navigationdrawer_demo" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="22" /> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name=".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> |
3. Open res ⇒ values ⇒ strings.xml and add below string values.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
<?xml version="1.0" encoding="utf-8"?> <resources> <string name="app_name">Android_NavigationDrawer_Demo</string> <string name="hello_world">Hello world!</string> <string name="action_settings">Settings</string> <string name="home">Home</string> <string name="messages">Messages</string> <string name="user_account">User Account</string> <string name="setting">Settings</string> <string name="about_us">About Us</string> <string name="icon_description">Navigation Drawer List Icons</string> <string name="profile_image">User profile image</string> <string name="user_name">Androhub</string> <string name="email">androhub@gmail.com</string> <string name="drawer_open">Drawer open</string> <string name="drawer_close">Drawer close</string> <string-array name="list_items"> <item>Home</item> <item>User Account</item> <item>Messages</item> <item>Settings</item> <item>About Us</item> </string-array> <string-array name="list_subitems"> <item>Default page</item> <item>User profile account</item> <item>Check your messages</item> <item>Change your settings</item> <item>Check about us</item> </string-array> </resources> |
4. Open res ⇒ values ⇒ colors.xml and add the below color values. If you don’t find colors.xml, create a new resource file with the name.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
<?xml version="1.0" encoding="utf-8"?> <resources> <color name="black">#000000</color> <color name="white">#FFFFFF</color> <color name="orange">#FF6600</color> <color name="light_blue">#CCFF</color> <color name="red">#ff00</color> <color name="grey">#d3d3d3</color> <color name="light_pink">#FFCC</color> <color name="purple">#DDAACC</color> <!-- Colors for material designing --> <color name="colorPrimary">#2979FF</color> <color name="colorPrimaryDark">#2962FF</color> <color name="textColorPrimary">#FFFFFF</color> <color name="windowBackground">#FFFFFF</color> <color name="colorAccent">#42A5F5</color> </resources> |
5. Open res ⇒ values ⇒ dimens.xml and add below dimensions.
1 2 3 4 5 6 7 8 9 10 |
<resources> <!-- Default screen margins, per the Android Design guidelines. --> <dimen name="activity_horizontal_margin">16dp</dimen> <dimen name="activity_vertical_margin">16dp</dimen> <dimen name="navigation_drawer_width">260dp</dimen> <dimen name="profile_layout_height">140dp</dimen> <dimen name="profile_image_size">50dp</dimen> </resources> |
6. Open styles.xml under res ⇒ values and add below styles. The styles defined in this styles.xml are common to all the android versions.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
<resources> <!-- Base application theme, dependent on API level. This theme is replaced by AppBaseTheme from res/values-vXX/styles.xml on newer devices. --> <style name="AppBaseTheme" parent="Theme.AppCompat.Light"> <item name="windowActionBar">false</item> <item name="android:textColorPrimary">@android:color/white</item> <item name="android:textColorSecondary">@android:color/white</item> <item name="actionMenuTextColor">@android:color/white</item> <item name="android:windowNoTitle">true</item> <item name="colorPrimary">@color/colorPrimary</item> <item name="colorPrimaryDark">@color/colorPrimaryDark</item> <item name="colorAccent">@color/colorAccent</item> <!-- Theme customizations available in newer API levels can go in res/values-vXX/styles.xml, while customizations related to backward-compatibility can go here. --> </style> <!-- Application theme. --> <style name="AppTheme" parent="AppBaseTheme"> <!-- All customizations that are NOT specific to a particular API-level can go here. --> </style> </resources> |
7. Now under res, create a folder named values-v21. Inside values-v21, create another styles.xml with the below styles. These styles are specific to Android Lollipop only.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<resources> <style name="AppBaseTheme" parent="Theme.AppCompat.Light"> <item name="windowActionBar">false</item> <item name="android:textColorPrimary">@android:color/white</item> <item name="android:textColorSecondary">@android:color/white</item> <item name="actionMenuTextColor">@android:color/white</item> <item name="android:windowNoTitle">true</item> <item name="colorPrimary">@color/colorPrimary</item> <item name="colorPrimaryDark">@color/colorPrimaryDark</item> <item name="colorAccent">@color/colorAccent</item> <item name="android:windowContentTransitions">true</item> <item name="android:windowAllowEnterTransitionOverlap">true</item> <item name="android:windowAllowReturnTransitionOverlap">true</item> <item name="android:windowSharedElementEnterTransition">@android:transition/move</item> <item name="android:windowSharedElementExitTransition">@android:transition/move</item> </style> </resources> |
8. Now, create a layout naming toolbar.xml in this layout create a toolbar set background and theme to it and this layout we are going to use in our other layouts.
1 2 3 4 5 6 7 8 9 10 11 |
<?xml version="1.0" encoding="utf-8"?> <!-- Toolbar in place of action bar for material designing --> <android.support.v7.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android" xmlns:local="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="?attr/colorPrimary" android:elevation="4dp" local:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" > </android.support.v7.widget.Toolbar> |
9. Android introduced a newer UI element called DrawerLayout for Navigation Drawer. Open your layout file (activity_main.xml) for main activity and type the following code.
Here FrameLayout is used to replace the main content using Fragments and it should be always the first child of the layout for z-index purpose.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 |
<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" > <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <!-- include use to reuse the layout here iclude the toolbar layout --> <include android:id="@+id/toolbar" layout="@layout/toolbar" > </include> <!-- Framelayout to display Fragments --> <FrameLayout android:id="@+id/frame_container" android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout> <RelativeLayout android:id="@+id/slider" android:layout_width="@dimen/navigation_drawer_width" android:layout_height="match_parent" android:layout_gravity="start" > <!-- Header view contains profile layout --> <RelativeLayout android:id="@+id/header_view" android:layout_width="fill_parent" android:layout_height="@dimen/profile_layout_height" android:layout_alignParentTop="true" android:background="#CCFFDD" android:gravity="center_vertical" android:padding="5dp" > <!-- Linear layout contains username and email id textview --> <LinearLayout android:id="@+id/profile_name_layout" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/profile_icon" android:layout_margin="10dp" android:layout_marginBottom="5dp" android:layout_marginTop="5dp" android:orientation="vertical" android:padding="5dp" > <TextView android:id="@+id/profile_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:text="@string/user_name" android:textColor="@color/black" android:textSize="18sp" /> <TextView android:id="@+id/profile_email" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/email" android:textColor="@color/black" android:textSize="12sp" /> </LinearLayout> <!-- user profile image --> <ImageView android:id="@+id/profile_icon" android:layout_width="@dimen/profile_image_size" android:layout_height="@dimen/profile_image_size" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" android:layout_marginLeft="10dp" android:layout_marginTop="10dp" android:contentDescription="@string/profile_image" android:padding="3dp" android:scaleType="centerInside" android:src="@drawable/ic_profile" /> </RelativeLayout> <View android:id="@+id/header_divider" android:layout_width="fill_parent" android:layout_height="2dp" android:layout_below="@+id/header_view" android:background="@color/grey" /> <!-- List view for navigation drawer item --> <ListView android:id="@+id/list_slidermenu" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_below="@+id/header_divider" android:background="@color/black" android:choiceMode="singleChoice" android:divider="@color/grey" android:dividerHeight="1dp" android:listSelector="@android:color/transparent" android:overScrollMode="never" android:scrollbars="none" /> </RelativeLayout> </android.support.v4.widget.DrawerLayout> |
10. For navigation items we have to create a custom view xml file that will inflate over ListView.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content" android:padding="7dp" > <ImageView android:id="@+id/icon" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" android:layout_margin="2dp" android:adjustViewBounds="true" android:layout_centerVertical="true" android:contentDescription="@string/icon_description" android:padding="3dp" android:scaleType="fitCenter" /> <TextView android:id="@+id/title" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_toRightOf="@+id/icon" android:gravity="start|center_vertical" android:paddingLeft="8dp" android:paddingRight="5dp" android:paddingTop="5dp" android:textColor="@color/white" android:textSize="15sp" android:textStyle="bold" /> <TextView android:id="@+id/subtitle" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_below="@+id/title" android:layout_toRightOf="@+id/icon" android:gravity="start|center_vertical" android:paddingLeft="8dp" android:paddingRight="5dp" android:paddingTop="5dp" android:textColor="@color/grey" android:textSize="13sp" /> </RelativeLayout> |
11. Now, for fragments that will shown on navigation item click we have to create fragments. So, we have to create xml according to number of menu items. This is one fragment xml file, similarly we can make many more.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="@color/red" android:gravity="center" android:orientation="vertical" > <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_gravity="center" android:gravity="center" android:text="@string/home" android:textColor="@color/white" android:textSize="30sp" /> </LinearLayout> |
12. Now, for all fragments we have to create separate class and add the following code to that class. This is for the one class file, Similarly we can create many more.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
package com.android_navigationdrawer_demo.fragments; import com.android_navigationdrawer_demo.R; import android.os.Bundle; import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; public class Home_Fragment extends Fragment{ @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view =inflater.inflate(R.layout.home_fragment, container,false); return view; } } |
13. Create a class named Navigations_Items.java with the below code. This model class is POJO class that defines each row in navigation drawer menu.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
package com.android_navigationdrawer_demo; public class Navigation_Items { String title, subtitle; Integer icon; public Navigation_Items(String title, String subtitle, Integer icon) { this.title = title; this.subtitle = subtitle; this.icon = icon; } public String getTitle() { return title; } public String getSubTitle() { return subtitle; } public Integer getIcon() { return icon; } } |
14. Now, create an Adapter Class for inflating view over ListView.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 |
package com.android_navigationdrawer_demo; import java.util.ArrayList; import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.ImageView; import android.widget.TextView; public class Navigation_Drawer_Adapter extends BaseAdapter { private ArrayList<Navigation_Items> arrayList; private Context context; public Navigation_Drawer_Adapter(Context context, ArrayList<Navigation_Items> arrayList) { this.context = context; this.arrayList = arrayList; } @Override public int getCount() { return arrayList.size(); } @Override public Navigation_Items getItem(int pos) { return arrayList.get(pos); } @Override public long getItemId(int pos) { return pos; } @Override public View getView(final int pos, View view, ViewGroup parent) { ViewHolder holder = null; if (view == null) { LayoutInflater inflater = (LayoutInflater) context .getSystemService(Context.LAYOUT_INFLATER_SERVICE); view = inflater.inflate(R.layout.custom_view, parent, false); holder = new ViewHolder(); holder.title = (TextView) view.findViewById(R.id.title); holder.subtitle = (TextView) view.findViewById(R.id.subtitle); holder.icon = (ImageView) view.findViewById(R.id.icon); view.setTag(holder); } else { holder = (ViewHolder) view.getTag(); } holder.title.setText(arrayList.get(pos).getTitle()); holder.subtitle.setText(arrayList.get(pos).getSubTitle()); holder.icon.setBackgroundResource(arrayList.get(pos).getIcon()); view.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { //Calling main activity selectPosition method to replpace the fragment new MainActivity().selectItem(pos); } }); return view; } public class ViewHolder { TextView title, subtitle; ImageView icon; } } |
15. Finally, add the following code to the MainActivity.java. In this activity we set DrawerLayout and set ActionBarDrawerToggle. On listview item click we set fragments over FrameLayout.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 |
package com.android_navigationdrawer_demo; import java.util.ArrayList; import android.content.res.Configuration; import android.os.Bundle; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.widget.DrawerLayout; import android.support.v7.app.ActionBarActivity; import android.support.v7.app.ActionBarDrawerToggle; import android.support.v7.widget.Toolbar; import android.view.View; import android.widget.ListView; import android.widget.RelativeLayout; import android.widget.Toast; import com.android_navigationdrawer_demo.fragments.AboutUs_Fragment; import com.android_navigationdrawer_demo.fragments.Home_Fragment; import com.android_navigationdrawer_demo.fragments.Messages_Fragment; import com.android_navigationdrawer_demo.fragments.Settings_Fragment; import com.android_navigationdrawer_demo.fragments.UserAccount_Fragment; public class MainActivity extends ActionBarActivity { private static DrawerLayout drawer; private static ActionBarDrawerToggle actionbarToggle; private static ArrayList<Navigation_Items> arrayList; private static Navigation_Drawer_Adapter adapter; private static ListView listview; private static FragmentManager fragment_manager; private static Toolbar toolbar; private static RelativeLayout left_slider; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); init(); populateListItems(); // Replace the default/home fragment if savedinstance is null if (savedInstanceState == null) { selectItem(0); } } void init() { drawer = (DrawerLayout) findViewById(R.id.drawer_layout); listview = (ListView) findViewById(R.id.list_slidermenu); toolbar = (Toolbar) findViewById(R.id.toolbar); left_slider = (RelativeLayout) findViewById(R.id.slider); // Fragment manager to manage fragment fragment_manager = getSupportFragmentManager(); arrayList = new ArrayList<Navigation_Items>(); // Setting actionbar toggle actionbarToggle = new ActionBarDrawerToggle(this, drawer, toolbar, R.string.drawer_open, R.string.drawer_close) { @Override public void onDrawerClosed(View drawerView) { Toast.makeText(MainActivity.this, "Drawer Close", Toast.LENGTH_SHORT).show(); super.onDrawerClosed(drawerView); } @Override public void onDrawerOpened(View drawerView) { Toast.makeText(MainActivity.this, "Drawer Open", Toast.LENGTH_SHORT).show(); super.onDrawerOpened(drawerView); } }; // Setting drawer listener drawer.setDrawerListener(actionbarToggle); } // Populate navigation drawer listitems void populateListItems() { Integer Icons[] = { R.drawable.ic_home, R.drawable.ic_user, R.drawable.ic_messages, R.drawable.ic_settings, R.drawable.ic_aboutus }; String title[] = getResources().getStringArray(R.array.list_items); String subtitle[] = getResources() .getStringArray(R.array.list_subitems); for (int i = 0; i < Icons.length; i++) { arrayList .add(new Navigation_Items(title[i], subtitle[i], Icons[i])); } adapter = new Navigation_Drawer_Adapter(MainActivity.this, arrayList); // Setting adapter listview.setAdapter(adapter); adapter.notifyDataSetChanged(); } // Select item method for replacing fragments public void selectItem(int position) { // Setting toolbar title toolbar.setTitle(arrayList.get(position).getTitle()); // Close drawer method closeDrawer(); switch (position) { case 0: replaceFragment(new Home_Fragment(), "Home"); break; case 1: replaceFragment(new UserAccount_Fragment(), "User Account"); break; case 2: replaceFragment(new Messages_Fragment(), "Messages"); break; case 3: replaceFragment(new Settings_Fragment(), "Settings"); break; case 4: replaceFragment(new AboutUs_Fragment(), "About Us"); break; } } // Replace fragment method void replaceFragment(Fragment fragment, String tag) { // First find the fragment by TAG and if it null then replace the // fragment else do nothing Fragment fr = fragment_manager.findFragmentByTag(tag); if (fr == null) { fragment_manager.beginTransaction() .replace(R.id.frame_container, fragment, tag).commit(); } } // close the open drawer void closeDrawer() { if (drawer.isDrawerOpen(left_slider)) { drawer.closeDrawer(left_slider); } } @Override public void onBackPressed() { // Call whenBackpressed method to do task whenBackPressed(); } // Method to be execute on back pressed void whenBackPressed() { Fragment fr = fragment_manager.findFragmentByTag("Home"); // First close the drawer if open if (drawer.isDrawerOpen(left_slider)) { drawer.closeDrawer(left_slider); } // else replace the home fragment if TAG is null else { if (fr == null) { selectItem(0); } // finally finish activity else { finish(); } } } @Override protected void onPostCreate(Bundle savedInstanceState) { super.onPostCreate(savedInstanceState); // Sync state for actionbar toggle actionbarToggle.syncState(); } @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); actionbarToggle.onConfigurationChanged(newConfig); } } |
16. Finally, all done – run the app and you will get the output as shown in video.
Thanks.
Subscribe to us and get the latest news.
3 Comments
madhav
Monday, August 8th, 2016hello sir, how can i set title for menus in navigation drawer ?
Madhav
Saturday, December 17th, 2016I had created same thing it works well when I run it on lollipop device but app crashed when I run it on API 19 don’t know what’s problem
Walter
Monday, October 22nd, 2018You are my hero! You solve my problems with this damn material design updating apps. You save me!