Custom Sliding menu Navigation Drawer with Listview

Introduction:
    The Sliding Menu navigation drawer is a list “ListView” of options on the left edge of the screen. It is hidden most of the time, but is revealed when the user swipes a finger from the left edge of the screen or, the user touches the app icon in the action bar.

demo:


Using this code

1. Add this SlidingMenuLayout into activity_main.xml with proper package name and class name

activity_main.xml

<com.example.navigation_listview.utills.SlidingMenuLayout 
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >

<LinearLayout
 xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="288dp"
 android:layout_height="match_parent"
 android:orientation="vertical" >

<RelativeLayout
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:background="#000000" >

<ListView
 android:id="@+id/list"
 android:layout_width="match_parent"
 android:layout_height="wrap_content" >
 </ListView>
</RelativeLayout>
</LinearLayout>

<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >

<!-- This acts as Actionbar -->

<RelativeLayout
 android:layout_width="match_parent"
 android:layout_height="@dimen/padding_50"
 android:background="#0174DF"
 android:orientation="horizontal" >

<Button
 android:id="@+id/button_menu"
 android:layout_width="40dp"
 android:layout_height="40dp"
 android:layout_alignParentLeft="true"
 android:layout_centerInParent="true"
 android:layout_marginLeft="4dp"
 android:background="@drawable/slide_menu_icon"
 android:onClick="toggleMenu" />

<TextView
 android:id="@+id/lk_profile_header_textview"
 android:layout_width="match_parent"
 android:layout_height="@dimen/padding_50"
 android:layout_centerInParent="true"
 android:gravity="center"
 android:padding="@dimen/padding_10"
 android:textAppearance="?android:attr/textAppearanceLarge"
 android:textColor="@color/white"
 android:textSize="@dimen/text_size_20"
 android:textStyle="bold"
 android:text="Navigation Drawer"
/>
</RelativeLayout>

<!-- This is where fragment will show up -->

<FrameLayout
 android:id="@+id/lk_profile_fragment"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:background="@color/white" >
</FrameLayout>
</LinearLayout>

</com.example.navigation_listview.utills.SlidingMenuLayout>

2. This Sliding Navigation is different from android inbuild navigation drawer 
    Use SlidingMenuLayout.java class for navigation drawer like Facebook Sliding Navigation.

SlidingMenuLayout.java

package com.example.navigation_listview.utills;

import android.content.Context;
import android.os.Handler;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.Interpolator;
import android.widget.LinearLayout;
import android.widget.Scroller;

public class SlidingMenuLayout extends LinearLayout {

private static final int SLIDING_DURATION = 500;
private static final int QUERY_INTERVAL = 16;
int mainLayoutWidth;
private View menu;
private View content;
private static int menuRightMargin = 50;

private enum MenuState {
HIDINGHIDDENSHOWINGSHOWN,
};

private int contentXOffset;
private MenuState currentMenuState = MenuState.HIDDEN;
private Scroller menuScroller = new Scroller(this.getContext(),
new EaseInInterpolator());
private Runnable menuRunnable = new MenuRunnable();
private Handler menuHandler = new Handler();
int prevX = 0;
boolean isDragging = false;
int lastDiffX = 0;

public SlidingMenuLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}

public SlidingMenuLayout(Context context) {
super(context);
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);

mainLayoutWidth = MeasureSpec.getSize(widthMeasureSpec);
menuRightMargin = mainLayoutWidth * 15 / 100;
}

@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();

menu = this.getChildAt(0);
content = this.getChildAt(1);
content.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
return SlidingMenuLayout.this.onContentTouch(v, event);
}
});
menu.setVisibility(View.GONE);
}

@Override
protected void onLayout(boolean changed, int left, int top, int right,
int bottom) {
if (changed) {
LayoutParams contentLayoutParams = (LayoutParams) content
.getLayoutParams();
contentLayoutParams.height = this.getHeight();
contentLayoutParams.width = this.getWidth();
LayoutParams menuLayoutParams = (LayoutParams) menu
.getLayoutParams();
menuLayoutParams.height = this.getHeight();
menuLayoutParams.width = this.getWidth() - menuRightMargin;
}
menu.layout(left, top, right - menuRightMargin, bottom);
content.layout(left + contentXOffset, top, right + contentXOffset,
bottom);

}

public void toggleMenu() {

if (currentMenuState == MenuState.HIDING
|| currentMenuState == MenuState.SHOWING)
return;

switch (currentMenuState) {
case HIDDEN:
currentMenuState = MenuState.SHOWING;
menu.setVisibility(View.VISIBLE);

menuScroller.startScroll(0, 0, menu.getLayoutParams().width, 0,
SLIDING_DURATION);
break;
case SHOWN:
currentMenuState = MenuState.HIDING;
menuScroller.startScroll(contentXOffset, 0, -contentXOffset, 0,
SLIDING_DURATION);
break;
default:
break;
}
menuHandler.postDelayed(menuRunnableQUERY_INTERVAL);
this.invalidate();
}

protected class MenuRunnable implements Runnable {
@Override
public void run() {
boolean isScrolling = menuScroller.computeScrollOffset();
adjustContentPosition(isScrolling);
}
}

private void adjustContentPosition(boolean isScrolling) {
int scrollerXOffset = menuScroller.getCurrX();

content.offsetLeftAndRight(scrollerXOffset - contentXOffset);

contentXOffset = scrollerXOffset;
this.invalidate();
if (isScrolling)
menuHandler.postDelayed(menuRunnableQUERY_INTERVAL);
else
this.onMenuSlidingComplete();
}

private void onMenuSlidingComplete() {
switch (currentMenuState) {
case SHOWING:
currentMenuState = MenuState.SHOWN;
break;
case HIDING:
currentMenuState = MenuState.HIDDEN;
menu.setVisibility(View.GONE);
break;
default:
return;
}
}

protected class EaseInInterpolator implements Interpolator {
@Override
public float getInterpolation(float t) {
return (float) Math.pow(t - 1, 5) + 1;
}

}

public boolean isMenuShown() {
return currentMenuState == MenuState.SHOWN;
}

public boolean onContentTouch(View v, MotionEvent event) {
if (currentMenuState == MenuState.HIDING
|| currentMenuState == MenuState.SHOWING)
return false;
int curX = (int) event.getRawX();
int diffX = 0;

switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:

prevX = curX;
return true;

case MotionEvent.ACTION_MOVE:
if (!isDragging) {
isDragging = true;
menu.setVisibility(View.VISIBLE);
}
diffX = curX - prevX;
if (contentXOffset + diffX <= 0) {
diffX = -contentXOffset;
else if (contentXOffset + diffX > mainLayoutWidth
menuRightMargin) {
diffX = mainLayoutWidth - menuRightMargin - contentXOffset;
}
content.offsetLeftAndRight(diffX);
contentXOffset += diffX;
this.invalidate();

prevX = curX;
lastDiffX = diffX;
return true;

case MotionEvent.ACTION_UP:
Log.d("MainLayout.java onContentTouch()""Up lastDiffX "
lastDiffX);

if (lastDiffX > 0) {
currentMenuState = MenuState.SHOWING;
menuScroller.startScroll(contentXOffset, 0,
menu.getLayoutParams().width - contentXOffset, 0,
SLIDING_DURATION);
else if (lastDiffX < 0) {
currentMenuState = MenuState.HIDING;
menuScroller.startScroll(contentXOffset, 0, -contentXOffset, 0,
SLIDING_DURATION);
}
menuHandler.postDelayed(menuRunnableQUERY_INTERVAL);
this.invalidate();
isDragging = false;
prevX = 0;
lastDiffX = 0;
return true;

default:
break;
}

return false;
}
}


3. Finally in MainActivity

MainActivity.java

package com.example.navigation_listview;

import java.util.ArrayList;
import com.example.navigation_listview.utills.SlidingMenuLayout;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.content.Context;
import android.graphics.Color;
import android.os.Bundle;
import android.view.View;
import android.view.Window;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ListView;

public class MainActivity extends FragmentActivity {

ListView Listview;
static SlidingMenuLayout slidingmenu_layout;
Context context;
Button lk_profile_menu,lk_profile_filter_btn;
ArrayList<String> values=new ArrayList<String>();
String[] nearby_values={"Theaters","Restaurants","Cafe","ATM","Shopping Malls","Railway stations","Taxi stands","Gas_station","Banks","Hospitals","Pharmacy","Bar","Parks","Gym"};

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
slidingmenu_layout = (SlidingMenuLayout) this.getLayoutInflater().inflate(
R.layout.activity_mainnull);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(slidingmenu_layout);
context=this;

//Declare first called activity name
StartProfileActivity fragment = new StartProfileActivity();
start_fragment(fragment);

//Sliding icon
lk_profile_menu = (Button) findViewById(R.id.button_menu);
lk_profile_menu.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// Show/hide the menu
 Listview.smoothScrollToPosition(0);
 toggleMenu(v);
 }
});
 Listview=(ListView)findViewById(R.id.list);
 Listview.setDividerHeight(2);
 Listview.setClickable(true);
 Listview.setBackgroundColor(Color.GRAY);
 ListAdapter adapter = new ListAdapter(context,nearby_values);
 Listview.setAdapter(adapter);
}

public static void toggleMenu(View v) 
{
 slidingmenu_layout.toggleMenu();
}

//Fragment
private void start_fragment(Fragment frag){
 FragmentManager fm = getSupportFragmentManager();
 FragmentTransaction fragmentTransaction = fm.beginTransaction();
 fragmentTransaction.replace(R.id.lk_profile_fragment, frag);
 fragmentTransaction.commit();
}

}


4. ListAdapter

  slidingmenu listview values and designs

ListAdaper.java

package com.example.navigation_listview;

import android.annotation.SuppressLint;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
public class ListAdapter extends BaseAdapter {

Context context;
String[] value;
LayoutInflater inflater;

public ListAdapter(Context context, String[] values) {
this.context = context;
this.value = values;
}

@Override
public int getCount() {
return value.length;
}

@Override
public Object getItem(int position) {
return null;
}

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

@SuppressLint("ViewHolder")
public View getView(int position, View convertView, ViewGroup parent) {

TextView txtNearby;
inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

View itemView = inflater.inflate(R.layout.list_item, parent, false);
txtNearby = (TextView) itemView.findViewById(R.id.title);
txtNearby.setText(value[position]);
return itemView;
}
}

5. ListAdapter xml file

list_item.xml

<?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="50dp"
android:orientation="horizontal"
android:background="@drawable/actionbar_style"
android:padding="5dp" >

<TextView
android:id="@+id/title"
android:layout_width="0dp"
android:layout_height="fill_parent"
android:layout_margin="10dp"
android:layout_weight="1"
android:textColor="#FFFFFF"
android:textSize="15dp"
android:text="aaa"/>


</LinearLayout>  


6.StartProfileActivity is the main screen for this application 

StartProfileActivity.java


package com.example.navigation_listview;

import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

public class StartProfileActivity extends Fragment{

static View view;
Context context;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
{
view = inflater.inflate(R.layout.activity_startprofilenull);
context=this.getActivity();
return view;

}
}


activity_startprofile.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="@drawable/lollipop"
android:orientation="vertical" >

</RelativeLayout>







                                                   
Previous
Next Post »

5 comments

Write comments
Unknown
AUTHOR
February 26, 2015 at 11:01 AM delete

Hi Rajendran,

Thanks For the nice tutorial, but i have found one issue, when we try to swipe the screen instead of clicking on the menu button and drag the screen till other end of the screen , screen goes to its position back.

Kindly let me know is there a fix.

Thanks & Regards.
Nagendra.

Reply
avatar
Anonymous
AUTHOR
April 11, 2015 at 1:09 PM delete

Hi,
Very simple Tutorial..Thanks for sharing your knowledge.I just have one query ,this
example is not supporting on gingerbread..I mean there is a minor space above my layout..i trying to fix by giving windows featur no title ..its not working in my case..So if there is any other wayto fix it please let me know...
Thanks You..

Reply
avatar
Unknown
AUTHOR
June 12, 2015 at 4:11 PM delete

Hi
Thanks for nice tutorial.
I stuck somewhere while implementing this.
I want to reduce the width of sliding menu.
Maybe I am so late, But hoping you will reply soon.
Thanks.

Reply
avatar
Unknown
AUTHOR
August 31, 2015 at 10:35 AM delete

Hi
Thanks for Sharing your knowledge .
Actually i successfully executed the Project .
I just need a little help from you as am stuck in the "SlidingMenuLayout" class.
I need is when i click on "lk_profile_menu" , toggle menu(v); is executing. All i need is to make the sliding screen appears half of the screen when i swipes from left to right.

Reply
avatar
Unknown
AUTHOR
August 31, 2015 at 10:42 AM delete

Hi
Thanks for sharing your knowledge.
Your tutorial is very useful and i successfully implemented it.
I need a little favour from you as on clicking the "lk_profile_menu" , "togglemenu(v)" is excuting which is in the "SlidingMenuLayout "
All i need is when we onclicking the menu button the listview should be appear half of the screen rather than sliding entire end of the screen .

Thanks and Regards.

Reply
avatar