Please enable JavaScript to view the comments powered by Disqus.

Android Sliding Menu using Navigation Drawer

A - Introduction Android Sliding Menu

Nowadays, a lot of Android applications use Sliding Menu to navigate between app’s modules/ screens. The Sliding Menu is hidden in the normal state and can be shown by swiping horizontally gesture or tapping on the app icon on the Action Bar.

Android Sliding Menu

Previously, if you want to create a Sliding Menu like this, the only way is using a third party library.

But now, Google support it with a newer concept called Navigation Drawer.

According to Google:

The navigation drawer is a panel that transitions in from the left edge of the screen and displays the app’s main navigation options.

In this post, we will learn how to create a Android Sliding Menu using Navigation Drawer.

B - Demo Application

1. Prepare resources

First of all, you need to download some images for the Sliding Menu and add them to the drawable folder:

  • Sliding menu icon: ic_drawer
  • Home icon: home
  • Settings icon: settings
  • Notifications icon: notifications
  • About icon: about

Open string.xml file, add some string variables for Sliding Menu items and icons name:

<?xml version="1.0" encoding="utf-8"?>
<resources>

<string name="app_name">Demo Sliding Menu</string>
<string name="action_settings">Settings</string>
<string name="hello_world">Hello world!</string>

<!-- Sliding Menu items -->
<string-array name="nav_drawer_items">
<item >Home</item>
<item >Notifications</item>
<item >Settings</item>
<item >About</item>
</string-array>

<!-- Sliding Menu item icons -->
<array name="nav_drawer_icons">
<item>@drawable/home</item>
<item>@drawable/notifications</item>
<item>@drawable/settings</item>
<item>@drawable/about</item>
</array>

</resources>

 

2. Edit main layout

Open activity_main.xml file and type the following code:

<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">

<!-- Framelayout to display Fragments -->
<FrameLayout
android:id="@+id/fragment_detail"
android:layout_width="match_parent"
android:layout_height="match_parent" />

<!-- Listview to display Sliding Menu -->
<ListView
android:id="@+id/lv_sliding_menu"
android:layout_width="240dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:choiceMode="singleChoice"
android:divider="#000"
android:dividerHeight="1dp"/>

</android.support.v4.widget.DrawerLayout>

 

The FrameLayout will hold the appropriate Fragment (default is Home fragment).

The ListView will role the Sliding Menu.

3. Create Adapter for Sliding Menu ListView

As I mentioned in the Custom ListView post, every Custom ListView need an Adapter. But before coding for the Adapter, We need to create some layouts for the Sliding Menu ListView.

Create a layout file under the res –> layouts folder and name it lv_item_sliding_menu.xml. This layout has a ImageView and TextView to display Sliding Menu item.

<?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="wrap_content"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:paddingTop="5dp" >

<ImageView
android:id="@+id/img_sliding_menu_item"
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:src="@drawable/home" />

<TextView
android:id="@+id/tv_sliding_menu_item"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="@+id/img_sliding_menu_item"
android:layout_toRightOf="@+id/img_sliding_menu_item"
android:text="Home"
android:layout_marginLeft="10dp"
android:textAppearance="?android:attr/textAppearanceMedium" />

</RelativeLayout>

 

To bind items to a ListView. We need an entity to describe that item.

Create SlidingMenuItem class with following properties:

public class SlidingMenuItem {
String title;
int icon;

public SlidingMenuItem(String title, int icon) {
this.title = title;
this.icon = icon;
}

public String getTitle() {
return title;
}

public void setTitle(String title) {
this.title = title;
}

public int getIcon() {
return icon;
}

public void setIcon(int icon) {
this.icon = icon;
}

}

 

Now, everything is ready to code the adapter.

Create SlidingMenuAdapter class that extends BaseAdapter:

public class SlidingMenuAdapter extends BaseAdapter {

private Context context;
private ArrayList<SlidingMenuItem> items;

public SlidingMenuAdapter(Context context, ArrayList<SlidingMenuItem> items) {
this.context = context;
this.items = items;
}

@Override
public int getCount() {
return items.size();
}

@Override
public Object getItem(int index) {
return items.get(index);
}

@Override
public long getItemId(int index) {
return index;
}

@Override
public View getView(int index, View view, ViewGroup arg2) {
if (view == null) {
LayoutInflater mInflater = (LayoutInflater)
context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
view = mInflater.inflate(R.layout.lv_item_sliding_menu, null);
}

ImageView imgIcon = (ImageView) view.findViewById(R.id.img_sliding_menu_item);
TextView txtTitle = (TextView) view.findViewById(R.id.tv_sliding_menu_item);

SlidingMenuItem item = items.get(index);

imgIcon.setImageResource(item.getIcon());
txtTitle.setText(item.getTitle());

return view;
}

}

 

Until now, we did every thing needed for the Sliding Menu ListView (the layout, the entity and the adapter).

Now, it’s time to implement it in the MainActivity with the following major steps:

  • Creating fragments for each Sliding Menu item
  • Create an instance of SlidingMenuAdapter and adding initial data
  • Assigning the adapter to Sliding Menu ListView
  • Handling on item click event to show the appropriate fragment for the clicked item

4. Create Fragments for each Sliding Menu items

Here, I only show to you the layout xml file and the code file of Home fragment. The others are similar and can be found in source code. Each fragment contains a TextView to describe the current screen. fragment_home.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="match_parent"
android:background="#B8E62E">

<TextView
android:id="@+id/tv_home"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:text="Home"
android:textAppearance="?android:attr/textAppearanceLarge" />

</RelativeLayout>

 

HomeFragment.java

public class HomeFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_home, container, false);
return rootView;
}
}

 

5. MainActivity

Open MainActivity.java and implement the remaining major steps. The following code is the completed code for MainActivity. I noted so many comments there so you guys can understand it easily:

public class MainActivity extends Activity {
private DrawerLayout drawerLayout;
private ListView lvSlidingMenu;
private ActionBarDrawerToggle drawerToggle; // Navigation Drawer titles
private CharSequence drawerTitle;
private CharSequence appTitle;

// Sliding Menu items
private String[] titles;
private TypedArray icons;
private ArrayList slidingMenuItems;
private SlidingMenuAdapter adapter;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
appTitle = drawerTitle = getTitle();

// Load resources
titles = getResources().getStringArray(R.array.nav_drawer_items);
icons = getResources().obtainTypedArray(R.array.nav_drawer_icons);

// Get Sliding Menu ListView istance
drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
lvSlidingMenu = (ListView) findViewById(R.id.lv_sliding_menu);
slidingMenuItems = new ArrayList();

// Creating and Adding SlidingMenuItems
slidingMenuItems.add(new SlidingMenuItem(titles[0], icons.getResourceId(0, -1)));
slidingMenuItems.add(new SlidingMenuItem(titles[1], icons.getResourceId(1, -1)));
slidingMenuItems.add(new SlidingMenuItem(titles[2], icons.getResourceId(2, -1)));
slidingMenuItems.add(new SlidingMenuItem(titles[3], icons.getResourceId(3, -1)));

// Recycle the typed array
icons.recycle();
lvSlidingMenu.setOnItemClickListener(new SlideMenuClickListener());

// Assign adapter to listview
adapter = new SlidingMenuAdapter(getApplicationContext(), slidingMenuItems);
lvSlidingMenu.setAdapter(adapter);

// Enable action bar app icon and behaving it as toggle button
getActionBar().setDisplayHomeAsUpEnabled(true);
getActionBar().setHomeButtonEnabled(true);
drawerToggle = new ActionBarDrawerToggle(this, drawerLayout, R.drawable.ic_drawer,
// Navigation Drawer
icon R.string.app_name,
//Navigation Drawer open - description for accessibility
R.string.app_name
// Navigation Drawer close - description for accessibility
) {
public void onDrawerClosed(View view) {
getActionBar().setTitle(appTitle);
invalidateOptionsMenu();
}

public void onDrawerOpened(View drawerView) {
getActionBar().setTitle(drawerTitle);
invalidateOptionsMenu();
}
}; drawerLayout.setDrawerListener(drawerToggle);
if (savedInstanceState == null) {
// On first time, show Home Fragment
displayView(0);
}
}

/**
* Slide menu item click listener *
*/

private class SlideMenuClickListener implements ListView.OnItemClickListener {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// Display appropriate fragment for selected item
displayView(position);
}
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Toggle Navigation Drawer on selecting action bar app icon/title
if (drawerToggle.onOptionsItemSelected(item)) {
return true;
}
// Handle action bar actions click
switch (item.getItemId()) {
case R.id.action_settings:
return true;
default:
return super.onOptionsItemSelected(item);
}
} /* * * Called when invalidateOptionsMenu() is triggered */

@Override
public boolean onPrepareOptionsMenu(Menu menu) {
// If Navigation Drawer is opened, hide the action items
boolean drawerOpen = drawerLayout.isDrawerOpen(lvSlidingMenu);
menu.findItem(R.id.action_settings).setVisible(!drawerOpen);
return super.onPrepareOptionsMenu(menu);
}

/**
* Display fragment view for selected Navigation Drawer list item *
*/

private void displayView(int position) {
Fragment fragment = null;
switch (position) {
case 0:
fragment = new HomeFragment();
break;
case 1:
fragment = new NotificationsFragment();
break;
case 2:
fragment = new SettingsFragment();
break;
case 3:
fragment = new AboutFragment();
break;
default:
break;
}
if (fragment != null) {
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction().replace(R.id.fragment_detail, fragment).commit();

// Update selected item and title, then close the drawer
lvSlidingMenu.setItemChecked(position, true);
lvSlidingMenu.setSelection(position);
setTitle(titles[position]);
drawerLayout.closeDrawer(lvSlidingMenu);
} else {
// Log error
Log.e("MainActivity", "Error in creating fragment");
}
}

@Override
public void setTitle(CharSequence title) {
appTitle = title;
getActionBar().setTitle(appTitle);
}

/**
* When using the ActionBarDrawerToggle, you must call it during * onPostCreate() and onConfigurationChanged()...
*/

@Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
// Sync the toggle state after onRestoreInstanceState has occurred.
drawerToggle.syncState();
}

@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
// Pass any configuration change to the drawer toggls
drawerToggle.onConfigurationChanged(newConfig);
}
}

 

Run the project and enjoy: Android Sliding Menu

C - Download source code

https://drive.google.com/file/d/0Bw3dwdSezn6faXJYQW5ibG5zWnM/edit?usp=sharing