OVERVIEW
Most modern apps have a sliding Navigation Drawer as the main navigation element. This seems to be the modern version replacement of the sliding TabHost which was the main navigation element a few years back. Note that this UI component is not natively available for Android versions older than 4.x (Icecream Sandwich). The example below is meant for apps targeting SDK 19 and later i.e. KitKat and later. Perhaps it might work for slightly older versions, but I am not sure.
METHODOLOGY
We create the NavigationDrawer as a Fragment which can be called from multiple Activities. So if your app has 5 Activity screens, then each of them will call this Fragment in code and also provide for it in their layouts. The example has a single Activity only called MainActivity
Layouts
The layout for MainActivity called activity_main.xml will have the root layout as
android.support.v4.widget.DrawerLayout
instead of the standard LinearLayout or RelativeLayout . Within the root layout there is a FrameLayout. Below the FrameLayout there be a single layout (LinearLayout in this case) which will hold the content for the Activity. Below this single layout, the fragment for the NavigationDrawer will be placed.
The NavigationDrawer itself consists of two layouts drawer_drawer.xml and drawer_header.xml .
As the names suggest, the main drawer component UI is set in drawer_drawer and the header UI is fixed in drawer_header.
Since we are going to put a menu with submenus within the drawer, we have two additional layout files – one to fix the UI for the top level menu groups list_group.xml and the second for the submenu items – list_item.xml
It is not necessary that the NavigationDrawer should only have menus. It can contain anything ,but most of the times a menu is the standard usage pattern for it.
Drawables
We have three drawables used here:
ic_drawer.png – the icon for drawer
actionbar_background.xml – background UI for the drawer when it is open
drawer_shadow_9.png – a 9 patch image for dropping a shadow when the drawer is visible
Values
dimens.xml – standard dimension values for the navigation drawer
styles.xml – style settings for the app
strings.xml – various string values used in the drawer
Assets
We will be putting icons for each menu item group in the Drawer, so we will use font awesome to put icons within our menu text. You can , use images or icons directly, but its easier to use font-awesome if you are just looking for standard icon notation.
Within our app folder, we will create assets folder and within that the fonts folder. Within the fonts folder will put the ttf file for font-awesome.
Classes
MainActivity.class – the main activity which will call the drawer.
NavigationDrawerFragment.class – the Class to handle the drawer fragment
ExpandableListDataPump.class – this provides the menu content
ExpandableListAdapter.class – the expandable list handler which will control the menu
FontManager.class – Utility class to access Font-awesome
SOURCE LISTINGS
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="navdrawer.test.com.navigationdrawertest"> <uses-sdk android:minSdkVersion="19" android:targetSdkVersion="23" /> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".MainActivity" android:label="@string/app_name" android:theme="@style/AppTheme"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
actionbar_background.xml
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> <gradient android:startColor="#444444" android:endColor="#aaaaaa" android:angle="0" /> </shape>
activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/main_layout" android:background="#ffffff" tools:context="navdrawer.test.com.navigationdrawertest.MainActivity"> <!-- As the main content view, the view below consumes the entire space available using match_parent in both dimensions. --> <FrameLayout android:id="@+id/container" android:layout_width="match_parent" android:layout_height="match_parent" /> <LinearLayout android:orientation="vertical" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_centerHorizontal="true" android:paddingTop="20dp" android:paddingBottom="20dp" android:paddingLeft="10dp" android:paddingRight="10dp" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Content comes here" /> </LinearLayout> <!-- The drawer is given a fixed width in dp and extends the full height of the container. --> <fragment android:id="@+id/navigation_drawer" android:layout_width="@dimen/navigation_drawer_width" android:layout_height="match_parent" android:layout_gravity="start" android:name="navdrawer.test.com.navigationdrawertest.NavigationDrawerFragment" tools:layout="@layout/drawer_drawer" /> </android.support.v4.widget.DrawerLayout>
drawer_drawer.xml
<ExpandableListView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/list_slidermenu" android:layout_width="300dp" android:layout_height="match_parent" android:layout_gravity="start" android:background="@drawable/actionbar_background" android:choiceMode="singleChoice" android:divider="#ffffff" android:dividerHeight="0.2dp" android:groupIndicator="@null" android:alpha="255" android:indicatorLeft="?android:attr/expandableListPreferredItemIndicatorLeft" > </ExpandableListView>
drawer_header.xml
<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" > <RelativeLayout android:id="@+id/RelativeLayout1" android:layout_width="match_parent" android:layout_height="80dp" android:background="#000000" > <TextView android:id="@+id/textDrawerHeading" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_alignParentTop="true" android:layout_margin="5dp" android:textAlignment="center" android:gravity="center_vertical" android:text="Header Text Comes Here" android:textAppearance="?android:attr/textAppearanceMedium" android:textColor="#ffffff" android:textStyle="bold" /> </RelativeLayout> </FrameLayout>
list_group.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@+id/listTitleIcon" android:layout_width="fill_parent" android:layout_height="wrap_content" android:paddingLeft="5dp" android:textColor="#ffffff" android:paddingTop="12dp" android:paddingBottom="12dp" android:layout_weight="0.60" android:textSize="18dp"/> <TextView android:id="@+id/listTitle" android:layout_width="fill_parent" android:layout_height="wrap_content" android:paddingLeft="5dp" android:textColor="#ffffff" android:paddingTop="12dp" android:paddingBottom="12dp" android:layout_weight="0.20"/> <TextView android:id="@+id/listTitleArrow" android:layout_width="fill_parent" android:layout_height="wrap_content" android:paddingRight="5dp" android:textColor="#ffffff" android:paddingTop="12dp" android:paddingBottom="12dp" android:layout_weight="0.60" android:textAlignment="viewEnd" android:text="X" android:textSize="18dp"/> </LinearLayout>
list_item.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="wrap_content"> <TextView android:id="@+id/expandedListItem" android:layout_width="fill_parent" android:layout_height="wrap_content" android:textColor="#ffffff" android:paddingLeft="60dp" android:paddingTop="10dp" android:paddingBottom="10dp" /> </LinearLayout>
dimens.xml
<resources> <!-- Default screen margins, per the Android Design guidelines. --> <dimen name="activity_horizontal_margin">16dp</dimen> <dimen name="activity_vertical_margin">16dp</dimen> <!-- Per the design guidelines, navigation drawers should be between 240dp and 320dp: https://developer.android.com/design/patterns/navigation-drawer.html --> <dimen name="navigation_drawer_width">240dp</dimen> </resources>
strings.xml
<resources> <string name="app_name">NavigationDrawerTest</string> <string name="action_settings">Settings</string> <string name="drawer_open"></string> <string name="drawer_close"></string> <string name="fa_glass"></string> <string name="fa_music"></string> <string name="fa_search"></string> <string name="fa_envelope_o"></string> <string name="fa_heart"></string> <string name="fa_star"></string> <string name="fa_star_o"></string> <string name="fa_user"></string> <string name="fa_film"></string> <string name="fa_chevron_right"></string> <string name="fa_chevron_down"></string> </resources>
styles.xml
<resources> <!-- Base application theme. --> <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar"> <!-- Customize your theme here. --> <item name="colorPrimary">@color/colorPrimary</item> <item name="colorPrimaryDark">@color/colorPrimaryDark</item> <item name="colorAccent">@color/colorAccent</item> </style> </resources>
ExpandableListAdapter.java
package navdrawer.test.com.navigationdrawertest; import java.util.HashMap; import java.util.List; import android.content.Context; import android.graphics.Typeface; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseExpandableListAdapter; import android.widget.ExpandableListView; import android.widget.TextView; import android.widget.ExpandableListView.OnGroupClickListener; public class ExpandableListAdapter extends BaseExpandableListAdapter { private Context context; private List<String> expandableListTitle; private HashMap<String, List<String>> expandableListDetail; public static int ITEM1 = 0; public static int ITEM2 = 1; public static int ITEM3 = 2; public static int ITEM4 = 3; public static int SUBITEM1_1 = 0; public static int SUBITEM1_2 = 1; public static int SUBITEM1_3 = 2; public static int SUBITEM1_4 = 3; public static int SUBITEM2_1 = 0; public static int SUBITEM2_2 = 1; public static int SUBITEM2_3 = 2; public static int SUBITEM2_4 = 3; public ExpandableListAdapter(Context context, List<String> expandableListTitle, HashMap<String, List<String>> expandableListDetail) { this.context = context; this.expandableListTitle = expandableListTitle; this.expandableListDetail = expandableListDetail; } @Override public Object getChild(int listPosition, int expandedListPosition) { return this.expandableListDetail.get(this.expandableListTitle.get(listPosition)) .get(expandedListPosition); } @Override public long getChildId(int listPosition, int expandedListPosition) { return expandedListPosition; } @Override public View getChildView(int listPosition, final int expandedListPosition, boolean isLastChild, View convertView, ViewGroup parent) { final String expandedListText = (String) getChild(listPosition, expandedListPosition); if (convertView == null) { LayoutInflater layoutInflater = (LayoutInflater) this.context .getSystemService(Context.LAYOUT_INFLATER_SERVICE); convertView = layoutInflater.inflate(R.layout.list_item, null); } TextView expandedListTextView = (TextView) convertView .findViewById(R.id.expandedListItem); expandedListTextView.setText(expandedListText); return convertView; } @Override public int getChildrenCount(int listPosition) { return this.expandableListDetail.get(this.expandableListTitle.get(listPosition)) .size(); } @Override public Object getGroup(int listPosition) { return this.expandableListTitle.get(listPosition); } @Override public int getGroupCount() { return this.expandableListTitle.size(); } @Override public long getGroupId(int listPosition) { return listPosition; } @Override public View getGroupView(int listPosition, boolean isExpanded, View convertView, ViewGroup parent) { String listTitle = (String) getGroup(listPosition); if (convertView == null) { LayoutInflater layoutInflater = (LayoutInflater) this.context. getSystemService(Context.LAYOUT_INFLATER_SERVICE); convertView = layoutInflater.inflate(R.layout.list_group, null); } TextView listTitleTextView = (TextView) convertView .findViewById(R.id.listTitle); listTitleTextView.setTypeface(null, Typeface.NORMAL); listTitleTextView.setText(listTitle); TextView listTitleTextArrowView = (TextView) convertView .findViewById(R.id.listTitleArrow); listTitleTextArrowView.setTypeface(null, Typeface.NORMAL); listTitleTextArrowView.setTypeface(FontManager.getTypeface(context, FontManager.FONTAWESOME)); // set icons for menu items TextView listTitleTextIconView = (TextView) convertView .findViewById(R.id.listTitleIcon); listTitleTextIconView.setTypeface(null, Typeface.NORMAL); listTitleTextIconView.setTypeface(FontManager.getTypeface(context, FontManager.FONTAWESOME)); if (listPosition == ITEM1) listTitleTextIconView.setText(context.getResources().getString(R.string.fa_glass)); else if (listPosition == ITEM2) listTitleTextIconView.setText(context.getResources().getString(R.string.fa_music)); else if (listPosition == ITEM3) listTitleTextIconView.setText(context.getResources().getString(R.string.fa_search)); else if (listPosition == ITEM4) listTitleTextIconView.setText(context.getResources().getString(R.string.fa_envelope_o)); // set arrow icons for relevant items if (listPosition == ITEM1 || listPosition == ITEM2) { if (!isExpanded) listTitleTextArrowView.setText(context.getResources().getString(R.string.fa_chevron_right)); else listTitleTextArrowView.setText(context.getResources().getString(R.string.fa_chevron_down)); } else { listTitleTextArrowView.setText(""); } return convertView; } @Override public boolean hasStableIds() { return false; } @Override public boolean isChildSelectable(int listPosition, int expandedListPosition) { return true; } }
ExpandableListDataPump.java
package navdrawer.test.com.navigationdrawertest; import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; public class ExpandableListDataPump { public static HashMap<String, List<String>> getData() { LinkedHashMap<String, List<String>> expandableListDetail = new LinkedHashMap<String, List<String>>(); List<String> menu3 = new ArrayList<String>(); List<String> menu4 = new ArrayList<String>(); List<String> list1 = new ArrayList<String>(); list1.add("Submenu 1"); list1.add("Submenu 2"); list1.add("Submenu 3"); list1.add("Submenu 4"); List<String> list2 = new ArrayList<String>(); list2.add("Submenu 1"); list2.add("Submenu 2"); list2.add("Submenu 3"); list2.add("Submenu 4"); expandableListDetail.put("Menu 1", list1); expandableListDetail.put("Menu 2", list2); expandableListDetail.put("Menu 3", menu3); expandableListDetail.put("Menu 4", menu4); return expandableListDetail; } }
FontManager.java
package navdrawer.test.com.navigationdrawertest; import android.content.Context; import android.graphics.Typeface; import android.view.View; /** * Created by amit on 26/3/16. */ public class FontManager { public static final String ROOT = "fonts/", FONTAWESOME = ROOT + "fontawesome-webfont.ttf"; public static Typeface getTypeface(Context context, String font) { return Typeface.createFromAsset(context.getAssets(), font); } }
MainActivity.java
package navdrawer.test.com.navigationdrawertest; import android.content.Intent; import android.support.v7.app.ActionBarActivity; import android.app.Activity; import android.support.v7.app.ActionBar; import android.support.v4.app.Fragment; import android.support.v4.app.ActionBarDrawerToggle; import android.support.v4.view.GravityCompat; import android.support.v4.widget.DrawerLayout; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; public class MainActivity extends ActionBarActivity implements NavigationDrawerFragment.NavigationDrawerCallbacks { private NavigationDrawerFragment mNavigationDrawerFragment; private CharSequence mTitle; private DrawerLayout mDrawerLayout; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); getSupportActionBar().setTitle("Home"); // Set up the drawer. mNavigationDrawerFragment = (NavigationDrawerFragment) getSupportFragmentManager().findFragmentById(R.id.navigation_drawer); mTitle = getTitle(); mNavigationDrawerFragment.setUp( R.id.navigation_drawer, (DrawerLayout) findViewById(R.id.main_layout)); mDrawerLayout = (DrawerLayout) findViewById(R.id.main_layout); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.menu_main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); //noinspection SimplifiableIfStatement if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); } @Override public void onNavigationDrawerItemSelected(int position) { // update the main content by replacing fragments } }
NavigationDrawerFragment.java
package navdrawer.test.com.navigationdrawertest; import android.content.Intent; import android.support.v7.app.ActionBarActivity; import android.app.Activity; import android.support.v7.app.ActionBar; import android.support.v4.app.Fragment; import android.support.v7.app.ActionBarDrawerToggle; import android.support.v4.view.GravityCompat; import android.support.v4.widget.DrawerLayout; import android.content.res.Configuration; import android.os.Bundle; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.ExpandableListView; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import android.widget.ExpandableListView.OnGroupCollapseListener; import android.widget.ExpandableListView.OnGroupExpandListener; /** * Fragment used for managing interactions for and presentation of a navigation drawer. * See the <a href="https://developer.android.com/design/patterns/navigation-drawer.html#Interaction"> * design guidelines</a> for a complete explanation of the behaviors implemented here. */ public class NavigationDrawerFragment extends Fragment { private static final String STATE_SELECTED_POSITION = "selected_navigation_drawer_position"; private NavigationDrawerCallbacks mCallbacks; private ActionBarDrawerToggle mDrawerToggle; private DrawerLayout mDrawerLayout; private ExpandableListView mDrawerListView; private View mFragmentContainerView; private int mCurrentSelectedPosition = 0; ArrayList<String> groupItem = new ArrayList<String>(); ArrayList<Object> childItem = new ArrayList<Object>(); List<String> expandableListTitle; HashMap<String, List<String>> expandableListDetail; public NavigationDrawerFragment() { } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); } @Override public void onActivityCreated (Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); // Indicate that this fragment would like to influence the set of actions in the action bar. setHasOptionsMenu(true); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { mDrawerListView = (ExpandableListView) inflater.inflate( R.layout.drawer_drawer, container, false); mDrawerListView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { selectItem(position); } }); expandableListDetail = ExpandableListDataPump.getData(); expandableListTitle = new ArrayList<String>(expandableListDetail.keySet()); mDrawerListView.setAdapter(new ExpandableListAdapter(getActivity(), expandableListTitle, expandableListDetail)); mDrawerListView.setOnGroupExpandListener(new OnGroupExpandListener() { @Override public void onGroupExpand(int groupPosition) { } }); mDrawerListView.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener() { public boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, long id) { boolean retVal = true; if (groupPosition == ExpandableListAdapter.ITEM1) { retVal = false; } else if (groupPosition == ExpandableListAdapter.ITEM2) { retVal = false; } else if (groupPosition == ExpandableListAdapter.ITEM3) { // call some activity here } else if (groupPosition == ExpandableListAdapter.ITEM4) { // call some activity here } return retVal; } }); mDrawerListView.setOnChildClickListener(new ExpandableListView.OnChildClickListener() { @Override public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) { if (groupPosition == ExpandableListAdapter.ITEM1) { if (childPosition == ExpandableListAdapter.SUBITEM1_1) { // call activity here } else if (childPosition == ExpandableListAdapter.SUBITEM1_2) { // call activity here } else if (childPosition == ExpandableListAdapter.SUBITEM1_3) { // call activity here } else if (childPosition == ExpandableListAdapter.SUBITEM1_4) { // call activity here } } else if (groupPosition == ExpandableListAdapter.ITEM2) { if (childPosition == ExpandableListAdapter.SUBITEM2_1) { // call activity here } else if (childPosition == ExpandableListAdapter.SUBITEM2_2) { // call activity here } else if (childPosition == ExpandableListAdapter.SUBITEM2_3) { // call activity here } else if (childPosition == ExpandableListAdapter.SUBITEM2_4) { // call activity here } } return true; } }); mDrawerListView.setItemChecked(mCurrentSelectedPosition, true); View header= inflater.inflate(R.layout.drawer_header, null); mDrawerListView.addHeaderView(header); return mDrawerListView; } public boolean isDrawerOpen() { return mDrawerLayout != null && mDrawerLayout.isDrawerOpen(mFragmentContainerView); } /** * Users of this fragment must call this method to set up the navigation drawer interactions. * * @param fragmentId The android:id of this fragment in its activity's layout. * @param drawerLayout The DrawerLayout containing this fragment's UI. */ public void setUp(int fragmentId, DrawerLayout drawerLayout) { mFragmentContainerView = getActivity().findViewById(fragmentId); mDrawerLayout = drawerLayout; // set a custom shadow that overlays the main content when the drawer opens mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START); // set up the drawer's list view with items and click listener ActionBar actionBar = getActionBar(); actionBar.setDisplayHomeAsUpEnabled(true); actionBar.setHomeButtonEnabled(true); // ActionBarDrawerToggle ties together the the proper interactions // between the navigation drawer and the action bar app icon. mDrawerToggle = new ActionBarDrawerToggle( getActivity(), /* host Activity */ mDrawerLayout, /* DrawerLayout object */ R.string.drawer_open, /* "open drawer" description for accessibility */ R.string.drawer_close /* "close drawer" description for accessibility */ ) { @Override public void onDrawerClosed(View drawerView) { super.onDrawerClosed(drawerView); getActionBar().setIcon(R.drawable.ic_drawer); if (!isAdded()) { return; } getActivity().supportInvalidateOptionsMenu(); // calls onPrepareOptionsMenu() } @Override public void onDrawerOpened(View drawerView) { super.onDrawerOpened(drawerView); if (!isAdded()) { return; } getActivity().supportInvalidateOptionsMenu(); // calls onPrepareOptionsMenu() } }; // Defer code dependent on restoration of previous instance state. mDrawerLayout.post(new Runnable() { @Override public void run() { mDrawerToggle.syncState(); } }); mDrawerLayout.setDrawerListener(mDrawerToggle); } private void selectItem(int position) { mCurrentSelectedPosition = position; if (mDrawerListView != null) { mDrawerListView.setItemChecked(position, true); } if (mDrawerLayout != null) { mDrawerLayout.closeDrawer(mFragmentContainerView); } if (mCallbacks != null) { mCallbacks.onNavigationDrawerItemSelected(position); } } @Override public void onAttach(Activity activity) { super.onAttach(activity); try { mCallbacks = (NavigationDrawerCallbacks) activity; } catch (ClassCastException e) { throw new ClassCastException("Activity must implement NavigationDrawerCallbacks."); } } @Override public void onDetach() { super.onDetach(); mCallbacks = null; } @Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putInt(STATE_SELECTED_POSITION, mCurrentSelectedPosition); } @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); // Forward the new configuration the drawer toggle component. mDrawerToggle.onConfigurationChanged(newConfig); } @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { // If the drawer is open, show the global app actions in the action bar. See also // showGlobalContextActionBar, which controls the top-left area of the action bar. if (mDrawerLayout != null && isDrawerOpen()) { inflater.inflate(R.menu.menu_main, menu); showGlobalContextActionBar(); } super.onCreateOptionsMenu(menu, inflater); } @Override public boolean onOptionsItemSelected(MenuItem item) { if (mDrawerToggle.onOptionsItemSelected(item)) { return true; } return super.onOptionsItemSelected(item); } /** * Per the navigation drawer design guidelines, updates the action bar to show the global app * 'context', rather than just what's in the current screen. */ private void showGlobalContextActionBar() { ActionBar actionBar = getActionBar(); actionBar.setDisplayShowTitleEnabled(true); actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD); } private ActionBar getActionBar() { return ((ActionBarActivity) getActivity()).getSupportActionBar(); } /** * Callbacks interface that all activities using this fragment must implement. */ public static interface NavigationDrawerCallbacks { /** * Called when an item in the navigation drawer is selected. */ void onNavigationDrawerItemSelected(int position); } }
SCREENSHOTS
Here is how the activity screen looks when the drawer is not open.
This is how it looks when the drawer opens on tapping the app icon.
The hamburger icon animates to turn into a left arrow. The reverse animation happens when the drawer is closed. If you dont see the icon changing, then make sure that in NavigationDrawerFragment.java you are importing
import android.support.v7.app.ActionBarDrawerToggle;
instead of
import android.support.v4.app.ActionBarDrawerToggle;
The complete source code is downloadable from this link.
Thank you for a great job.
But It is not working for less than sdk 19.
Please, tell me how I can use it on older SDK ?
facing same problem…
@Abdi @Dipawali. As far as I know the navigation drawer is part of the official SDK only from version 19 onwards. If you are making an older version app then you can try using the Support library which has the navigation drawer functionality but the code will be different for that and all features might not work. Another alternative is to use a third party sliding menu which can run on older versions.
hi thank you for the good tutorial,
i want to open each fragment when user click onSetOnclickListener not as activity as a fragment
how do that please help
@atta . You can perform a Fragment Transaction in an onclick handler. This works on fragments and not on the whole Activity. You can find the documentation here:
https://developer.android.com/guide/components/fragments.html#Transactions
thank you so much this really helpfully.
i have question if you can to help ,
can you give me step to make the navigation drawer above Actionbar (toolbar) ?
@muller.
You can find your solution here:
http://stackoverflow.com/questions/23294954/android-navigation-drawer-on-top-actionbar
thank you m8 for your reply , i will check it , and i am so sorry if bothered you
i checked it and work fine ty ,
sorry last question , any step for fragment this items and subitems , i need step work with ur codes . i am sorry for bothering you , i still learn and i love to test alot of project to learn more
and can you tell me how to put this code , with ur code ! i tried many way but all time i got error
i need to use this code to collapse group
http://stackoverflow.com/a/32190162/2428653
int lastExpandedGroupPosition = 0;
[code]
@Override
public void onGroupExpanded(int groupPosition){
//collapse the old expanded group, if not the same
//as new group to expand
if(groupPosition != lastExpandedGroupPosition){
listView.collapseGroup(lastExpandedGroupPosition);
}
super.onGroupExpanded(groupPosition);
lastExpandedGroupPosition = groupPosition;
}
@muller. It is not really much use to put each item in a fragment because a fragment represents a complete Activity so it is not meant to just be a simple UI. If you want to have complex displays for each item, then its better to create an xml layout in a separate file and then inflate it for the particular list item at runtime.
What is the error you are getting when using onGroupExpanded
🙁
as i told you i just start to learn it ,
if you can help me just for some code
when i press on Menu 3 Open xml file
when i press on Submenu 1 Open xml file ,
i search on google and find meany way, but every time i try to add it, i got error , and some time work , but when i press nothing happens, really i am so sorry if i am bothering you 🙁
@muller.
Sorry I really am very busy with other work. Hopefully you can find a solution if you keep trying.
Hello, I have implemented the nav drawer in my app. I have a question, what will be the position of the child, when the second group is expanded. Where you have overrided – onNavigationDrawerItemSelected, and typed call fragments here. What will be the position of the child to call the fragment. Thank you!