In most of the android applications like Facebook , Google plus , ,you tube, amazon kindle , true caller .. etc you have seen a side menu which appears on click of an icon on top left corner or by dragging on to the screen from left to right , so here in this tutorial we shall see how to create the sliding menu for you android application .


Note : Drawer Layout was added to Android Support Library, revision 19.0.1
           Developer site : Support library


Design Pattern

Display
  • By swiping from the left edge of the screen.
  • By touching the application icon on the action bar.

Dismiss 
  • Touching the app icon (at top left corner) .
  • Touching the content outside drawer .
  • Swapping anywhere on the Screen .
  • Pressing Back
 For More Brief on design visit developer site Navigation Drawer .

In this tutorial we will see an example in which i  have added three items for listview , onclick of any particular item of the list , the corresponding content will be displayed .

 Below is the diagrammatic representation .



Lets See An Example
Project Detail
Project Name SlidingMenu
Package com.pavan.slidingmenu
Minimum SDK API 8
Target SDK API 17
Theme Holo Light Theme

While making this tutorial i was not able to import Drawer class ,reason i have not updated the Development environment with support library so to do that follow the below steps

(do if you are not able to import drawer class or getting error )

 1) In Eclipse right-click over the project, then choose Android Tools  >  Add Support Library
 2) Accept License and then click Install

String Constant


Before i start coding i will initialize all the strings and arrays inside the inside res/strings.xml . and also i  have kept  all the images inside the drawable folder of project

file : strings.xml

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

    <string name="app_name">SlidingMenu</string>
    <string name="action_settings">Settings</string>
    <string name="hello_world">Hello world!</string>
    <string name="imgdesc">imgdesc</string>

    <string-array name="titles">
        <item>Facebook</item>
        <item>Google-Plus</item>
        <item>TutorialsBuzz</item>
    </string-array>

    <array name="icons">
        <item>@drawable/fb</item>
        <item>@drawable/gplus</item>
        <item>@drawable/tb</item>
    </array>

</resources>

Main XML Layout


Create a main layout which contains DrawerLayout as parent view and add FrameLayout and ListView  as a child to it , the framelayout act as the main content view and listview act as menu list

file : activity_main.xml
<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/frame_container"
                android:layout_width="match_parent"
                android:layout_height="match_parent" />

    <!-- The navigation drawer list -->
         <ListView
             android:id="@+id/slider_list"
             android:layout_width="240dp"
             android:layout_height="match_parent"
             android:layout_gravity="start"
             android:background="#ffffff"
             android:choiceMode="singleChoice"
             android:divider="@android:color/transparent"
             android:dividerHeight="0dp" />

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


ListView Set Up


I am setting up a Custom ListView for ListView Inside which contains one ImageView and one TextView, so create list_item.xml inside layout directory ,this layout is used to defines the design of each row items in a list view .

file : list_tem.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="48dp"
    android:padding="5dp" >

    <ImageView
        android:id="@+id/icon"
        android:layout_width="50dp"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_centerVertical="true"
        android:layout_marginLeft="12dp"
        android:layout_marginRight="12dp"
        android:contentDescription="@string/imgdesc" />

    <TextView
        android:id="@+id/title"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_marginTop="10dp"
        android:layout_toRightOf="@id/icon"
        android:gravity="center_vertical"
        android:textColor="#000000"
        android:textSize="20sp" />

</RelativeLayout>

Bean Class

Create a Bean Class RowItem which is used for setting and getting row data's of each items in ListView ( icons and titles).

file : RowItem.java
package com.pavan.slidingmenu;

public class RowItem {

     private String title;
     private int icon;

     public RowItem(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;
    }

}

Adapter

Create a Custom adapter which extends BaseAdapter , this is used for inflating each row items of the listview .

file : CustomAdapter.java
package com.pavan.slidingmenu;

import java.util.List;

import android.app.Activity;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;

public class CustomAdapter extends BaseAdapter {

 Context context;
 List<RowItem> rowItem;

 CustomAdapter(Context context, List<RowItem> rowItem) {
  this.context = context;
  this.rowItem = rowItem;
 }

 private class ViewHolder {
  ImageView icon;
  TextView title;
 }

 @Override
 public View getView(int position, View convertView, ViewGroup parent) {

  ViewHolder holder = null;

  LayoutInflater mInflater = (LayoutInflater) context
    .getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
  if (convertView == null) {
   convertView = mInflater.inflate(R.layout.list_item, null);
   holder = new ViewHolder();
   holder.icon = (ImageView) convertView.findViewById(R.id.icon);
   holder.title = (TextView) convertView.findViewById(R.id.title);

   RowItem row_pos = rowItem.get(position);
   // setting the image resource and title
   holder.icon.setImageResource(row_pos.getIcon());
   holder.title.setText(row_pos.getTitle());
   convertView.setTag(holder);

  } else {
   holder = (ViewHolder) convertView.getTag();
  }

  return convertView;

 }

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

 @Override
 public Object getItem(int position) {
  return rowItem.get(position);
 }

 @Override
 public long getItemId(int position) {
  return rowItem.indexOf(getItem(position));
 }

}

Create Fragment for each Items of the ListView


Create fragment for each items of the listview , below you can see i have create fragment for facebook item of listview

file : fb_fragment.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" >

    <ImageView
        android:id="@+id/imageView1"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="148dp"
        android:src="@drawable/fb" />

</RelativeLayout>
file : FB_Fragment.java

package com.pavan.slidingmenu.slidelist;

import com.pavan.slidingmenu.R;
import android.annotation.SuppressLint;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

  @SuppressLint("NewApi")
   public class FB_Fragment extends Fragment {

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


Similarly Create Two More Fragment for Remaining two Items of ListView .

                                            

Handling ListView Item click listener


Create a inner class called SlideitemListener , Inside the MainActivity class , and override onItemClick method inside this method call updateDisplay() method by passing position as a parameter to it and then inside updateDisplay by knowing  the position clicked ,we are replacing the current fragment with the respective fragment associated with the items of listview . you can find the updateDisplay method inside the MainActivity class .

mDrawerList.setAdapter(adapter);
mDrawerList.setOnItemClickListener(new SlideitemListener());
 ...
 ...
 ...
 class SlideitemListener implements ListView.OnItemClickListener
  {
      @Override
       public void onItemClick(AdapterView parent, View view, int position, long id)
       {
           updateDisplay(position);
       }
  }

Main Activity


file : MainActivity.java
package com.pavan.slidingmenu;

import java.util.ArrayList;
import java.util.List;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentManager;
import android.content.res.Configuration;
import android.content.res.TypedArray;
import android.os.Bundle;
import android.support.v4.app.ActionBarDrawerToggle;
import android.support.v4.widget.DrawerLayout;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;

import com.pavan.slidingmenu.slidelist.FB_Fragment;
import com.pavan.slidingmenu.slidelist.GP_Fragment;
import com.pavan.slidingmenu.slidelist.TB_Fragment;

public class MainActivity extends Activity {

 String[] menutitles;
 TypedArray menuIcons;

 // nav drawer title
 private CharSequence mDrawerTitle;
 private CharSequence mTitle;

 private DrawerLayout mDrawerLayout;
 private ListView mDrawerList;
 private ActionBarDrawerToggle mDrawerToggle;

 private List<RowItem> rowItems;
 private CustomAdapter adapter;

 @SuppressLint("NewApi")
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  // TODO Auto-generated method stub
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);

  mTitle = mDrawerTitle = getTitle();

  menutitles = getResources().getStringArray(R.array.titles);
  menuIcons = getResources().obtainTypedArray(R.array.icons);

  mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
  mDrawerList = (ListView) findViewById(R.id.slider_list);

  rowItems = new ArrayList<RowItem>();

  for (int i = 0; i < menutitles.length; i++) {
   RowItem items = new RowItem(menutitles[i], menuIcons.getResourceId(
     i, -1));
   rowItems.add(items);
  }

  menuIcons.recycle();

  adapter = new CustomAdapter(getApplicationContext(), rowItems);

  mDrawerList.setAdapter(adapter);
  mDrawerList.setOnItemClickListener(new SlideitemListener());

  // enabling action bar app icon and behaving it as toggle button
  getActionBar().setDisplayHomeAsUpEnabled(true);
  getActionBar().setHomeButtonEnabled(true);

  mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout,
    R.drawable.ic_drawer, R.string.app_name,R.string.app_name) {
       public void onDrawerClosed(View view) {
         getActionBar().setTitle(mTitle);
         // calling onPrepareOptionsMenu() to show action bar icons
         invalidateOptionsMenu();
       }

        public void onDrawerOpened(View drawerView) {
              getActionBar().setTitle(mDrawerTitle);
               // calling onPrepareOptionsMenu() to hide action bar icons
              invalidateOptionsMenu();
         }
  };

  mDrawerLayout.setDrawerListener(mDrawerToggle);

  if (savedInstanceState == null) {
       // on first time display view for first nav item
       updateDisplay(0);
     }
 }

 class SlideitemListener implements ListView.OnItemClickListener {
       @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id)
            {
                 updateDisplay(position);
            }

      }

 private void updateDisplay(int position) {
      Fragment fragment = null;
         switch (position) {
               case 0:
                           fragment = new FB_Fragment();
                            break;
               case 1:
                           fragment = new GP_Fragment();
                           break;
               case 2:
                          fragment = new TB_Fragment();
                           break;
              default:
                         break;
    }

  if (fragment != null) {
            FragmentManager fragmentManager = getFragmentManager();
             fragmentManager.beginTransaction().replace(R.id.frame_container, fragment).commit();
            // update selected item and title, then close the drawer
            setTitle(menutitles[position]);
             mDrawerLayout.closeDrawer(mDrawerList);
  } else {
              // error in creating fragment
              Log.e("MainActivity", "Error in creating fragment");
            }

  }

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

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

 @Override
 public boolean onOptionsItemSelected(MenuItem item) {
  // toggle nav drawer on selecting action bar app icon/title
          if (mDrawerToggle.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 nav drawer is opened, hide the action items
                boolean drawerOpen = mDrawerLayout.isDrawerOpen(mDrawerList);
                menu.findItem(R.id.action_settings).setVisible(!drawerOpen);
                return super.onPrepareOptionsMenu(menu);
      }

 /**
  * 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.
         mDrawerToggle.syncState();
   }

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

}





0 comments:

Post a Comment

 
Top