Building Sliding Menu like Facebook by a library in Android

    Sliding menu is may be the most popular UI design in mobile application and Android is not also an exception. It's very convenient in switching to the similar feature/choice or simply is changing to another app screen!

    If you follow my blog frequently, you can see that I also had 2 posts about Sliding Menu previously:
  • The first way is using a very famous library from Jeremy Feinstein (Read this post HERE). It's the most popular choice in many applications till now. The weakness of this library is it has not been updated by author and not support for AppCompat themes, depend on ActionBarSherlock, so it's seem obsolete now - when Material Design has affirmed its position, become the official style for Android application.
  • The second way is building a Sliding Menu yourself. It's not too much complicated and if you pay attention to animation, you can create a good one, too! (Read this post HERE).
   By this post, I would like to present one more external library which I think it's quite well in sliding-animation and support well for both left and right side sliding menu and not depend on any theme (so you can build it in a Material Design theme). Implementing it is also not very hard, I'll make a sample project with a screen which have a right-menu (like Facebook application), source code now available on @Github.
    DEMO VIDEO:

Importing library

    Go to library page on Github and clone or download zip file to your computer. After extracting, you will see the 'library' folder
    Importing this folder as an Android module (read my previous post for details), you'll have a new module in your project named library:
    Make sure that your modules build.gradle files have same compileSdkVersion, buildToolsVersion, minSdkVersion,...:
app/build.gradle
apply plugin: 'com.android.application'

android {
    compileSdkVersion 24
    buildToolsVersion "24.0.0"

    defaultConfig {
        applicationId "info.devexchanges.fbslidingmenu"
        minSdkVersion 14
        targetSdkVersion 24
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(include: ['*.jar'], dir: 'libs')
    compile 'com.android.support:appcompat-v7:24.0.0'
    compile project(':library')
}
library/build.gradle
apply plugin: 'com.android.library'

android {
    compileSdkVersion 24
    buildToolsVersion "24.0.0"

    defaultConfig {
        minSdkVersion 14
        targetSdkVersion 24
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:24.0.0'
}

Principles of creating the sliding menu

    In onCreate() of the Activity, firstly, you must initialize a CustomMenu object:
slidingMenu = new CustomMenu(this);
    After that, set content view (main view), shadow drawable and menu view by this code:
//Setting Content Layout
slidingMenu.setContentView(R.layout.activity_main);
slidingMenu.setRightShadow(R.drawable.shadow_right);

//Setting the right menu
ImageView rightMenu = new ImageView(this);
rightMenu.setBackgroundResource(R.drawable.left_view);
customMenu.setRightMenu(rightMenu);
    After all, set this slidingMenu as the content view of your Activity:
setContentView(slidingMenu);
    In the real application, the menu view usually is a ListView, not an ImageView like this. In my project, I will do this.

Demo project: step by step

    Declaring a xml layout contains only a ListView, it will work as the menu view:
layout_right_menu.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#39ac73">

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

</LinearLayout>
    The CustomMenu content view (main view), only a Toolbar and an empty LinearLayout, Fragments will be replaced here later:
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="info.devexchanges.fbslidingmenu.MainActivity">

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="@color/colorPrimary"
        android:orientation="horizontal"
        app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
        app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

    </android.support.v7.widget.Toolbar>

    <LinearLayout
        android:id="@+id/main_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@id/toolbar"
        android:orientation="vertical" />
</RelativeLayout>
    In the activity programmatically code, in order to design a "toggle button" in the right side, you must create an option menu file and inflating it to Toolbar. Setting the right menu, shadow like description above and creating the menu data, we have full main activity code:
MainActivity.java
package info.devexchanges.fbslidingmenu;

import android.app.Fragment;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.Toolbar;
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 java.util.Arrays;
import java.util.List;

import cn.tovi.CustomMenu;
import info.devexchanges.fbslidingmenu.fragment.ButtonFragment;
import info.devexchanges.fbslidingmenu.fragment.CheckBoxFragment;
import info.devexchanges.fbslidingmenu.fragment.ImageViewFragment;
import info.devexchanges.fbslidingmenu.fragment.MainFragment;
import info.devexchanges.fbslidingmenu.fragment.RadioGroupFragment;
import info.devexchanges.fbslidingmenu.fragment.SeekBarFragment;
import info.devexchanges.fbslidingmenu.fragment.SwitchFragment;
import info.devexchanges.fbslidingmenu.fragment.TextViewFragment;

public class MainActivity extends AppCompatActivity {

    private Toolbar toolbar;
    private CustomMenu slidingMenu;
    private ListView slidingListView;
    private View rightMenuView;

    private List<String> strings;
    private Fragment currentFragment;

    private final static String TAG = MainActivity.class.getSimpleName();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        slidingMenu = new CustomMenu(this);

        //Setting Content Layout
        slidingMenu.setContentView(R.layout.activity_main);
        slidingMenu.setRightShadow(R.drawable.shadow_right);

        //Setting the right menu
        rightMenuView = getLayoutInflater().inflate(R.layout.layout_right_menu, slidingMenu, false);
        slidingListView = (ListView) rightMenuView.findViewById(R.id.list);
        //locate menu in the right
        slidingMenu.setRightMenu(rightMenuView);

        //set content view for activity after all
        setContentView(slidingMenu);

        toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        //setting data for right listview
        setMenuListViewAdapter();

        //handling right listview click listener
        slidingListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) {
                if (position == 2) {
                    replaceFragment(new TextViewFragment());
                } else if (position ==1) {
                    replaceFragment(new ButtonFragment());
                } else if (position == 0) {
                    replaceFragment(new MainFragment());
                } else if (position == 3) {
                    replaceFragment(new ImageViewFragment());
                } else if (position == 4) {
                    replaceFragment(new SwitchFragment());
                } else if (position == 5) {
                    replaceFragment(new CheckBoxFragment());
                } else if (position == 6) {
                    replaceFragment(new RadioGroupFragment());
                } else {
                    replaceFragment(new SeekBarFragment());
                }
                toggleSlidingMenu();
            }
        });

        //replace main fragment when first create activity
        MainFragment fragment = new MainFragment();
        FragmentManager fm = getFragmentManager();
        FragmentTransaction ft = fm.beginTransaction();
        ft.replace(R.id.main_view, fragment);
        ft.commit();
        currentFragment = fragment;
    }

    private void setMenuListViewAdapter() {
        strings = Arrays.asList(getResources().getStringArray(R.array.right_menu));
        ArrayAdapter adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, strings);
        slidingListView.setAdapter(adapter);
    }

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

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        if (item.getItemId() == R.id.menu) {
            toggleSlidingMenu();
        }
        return super.onOptionsItemSelected(item);
    }

    private void toggleSlidingMenu() {
        if (slidingMenu.getState() == CustomMenu.State.CLOSE_MENU) {
            slidingMenu.openRightMenuIfPossible();
        } else if (slidingMenu.getState() == CustomMenu.State.RIGHT_MENU_OPENS) {
            slidingMenu.closeMenu();
        } else {
            Log.e(TAG, "CustomMenu State:" + slidingMenu.getState());
        }
    }

    private void replaceFragment(Fragment fragment) {
        if (!fragment.getClass().getSimpleName().equals(currentFragment.getClass().getSimpleName())) {
            // Replace fragment main when activity start
            FragmentManager fm = getFragmentManager();
            FragmentTransaction ft = fm.beginTransaction();
            ft.replace(R.id.main_view, fragment);
            ft.addToBackStack("fragment");
            ft.commit();
            currentFragment = fragment;
        }
    }
}
    And this is menu file:
res/menu/menu_main.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <item
        android:id="@+id/menu"
        app:showAsAction="always"
        android:icon="@drawable/menu"
        android:title="Menu" />
</menu>
    As you can see, the MainFragment will be replaced to main view when app start. Other fragments also replaced when user click at any menu view items. It has total 9 fragments in my sample project:
     For example, this is code for ButtonFragment, after click Button here, user will be redirect to other activity:
ButtonFragment.java
package info.devexchanges.fbslidingmenu.fragment;

import android.app.Fragment;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import info.devexchanges.fbslidingmenu.DetinationActivity;
import info.devexchanges.fbslidingmenu.R;

public class ButtonFragment extends Fragment {

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_button, container, false);
        View btnGo = view.findViewById(R.id.btn_go);

        //go to other activity when button clicked
        btnGo.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(getActivity(), DetinationActivity.class);
                startActivity(intent);
            }
        });

        return view;
    }
}
    And it's layout:
fragment_button.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:padding="@dimen/activity_horizontal_margin">

    <Button
        android:id="@+id/btn_go"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:text="Go to other Activity" />

</RelativeLayout>
    The "desination activity" code:
DestinationActivity.java

package info.devexchanges.fbslidingmenu;

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.MenuItem;

public class DetinationActivity extends AppCompatActivity {

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_des);
        Toolbar toolbar = (Toolbar)findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        getSupportActionBar().setHomeButtonEnabled(true);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        if (item.getItemId() == android.R.id.home) finish();

        return super.onOptionsItemSelected(item);
    }

    @Override
    public void onBackPressed() {
        finish();
    }
}
activity_des.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="@color/colorPrimary"
        android:orientation="horizontal"
        app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
        app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

    </android.support.v7.widget.Toolbar>

    <TextView
        android:layout_centerInParent="true"
        android:id="@+id/text_view"
        android:textStyle="bold"
        android:text="Go to here from a Fragment in the Sliding Menu Activity"
        android:padding="@dimen/activity_horizontal_margin"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

</RelativeLayout>
    Other fragments code, you can see at my project on Github.
    Strings resource:
strings.xml
<resources>
    <string name="app_name">Sliding Menu like Facebook</string>
    <string name="demo">This is Demo of making Sliding menu like Facebook application</string>

    <string-array name="right_menu">
        <item>MainLayout</item>
        <item>Button</item>
        <item>TextView</item>
        <item>ImageView</item>
        <item>Switch</item>
        <item>CheckBox</item>
        <item>RadioGroup</item>
        <item>SeekBar</item>
    </string-array>
</resources>
    As you see above, I used Toolbar in activities layout, so your app must use a "no Action Bar theme":
styles.xml
<resources>

    <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
    </style>

</resources>

Running application

    This is our output:
    Menu view is visible (when click toggle button or drag screen):

Conclusions

    By searching on Internet, you may find out another libraries of another ways to make this popular UI and they can work better than this. And once again, through this post, I hope that you have one more choice for designing a sliding menu like Facebook application to apply to your own product.  Moreover, you can visit this tag link to read all posts about Sliding menu. Thanks for reading, readers!
    Reference to the library page: https://github.com/flyfei/CustomMenu

Creating your own sliding menu like Facebook with Material design theme in Android

    There is a library which allows Android developers to easily create applications with slide-in menus like Facebook or LinkedIn made by Jeremy Feinstein, it has been widely used and become very popular. I also had a post about this library in order to guiding my readers to use it. The disadvantages of it is not update the new Android design technology (the last commit was 2 years ago), so if you implement it in your project, you cannot make your app available in Material design style - the new flat-design technology from Google.
    Dealing with this situation, we should find out the way to creating a sliding menu ourself. This post is a tutorial for you about this problem with using some features in Material design technology.
    DEMO VIDEO:

Prerequisites

    After starting a new Android project, make sure that you use a "no Action Bar" theme from Appcompat library with your project:
styles.xml
<resources>

    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
    </style>

</resources>

Making a sliding layout

    The most important work is designing a "sliding layout", it contains 2 parts: menu view (on the left) and main view (content view). We will let the menu view hold still, while moving the content view. The content view usually sits on top of the menu view and cover the entire screen:
    Name this layout class is SlidingLayout, provide constructors first:
public class SlidingLayout extends LinearLayout {

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

    public SlidingLayout(Context context) {
        super(context);
    }
}
    Now, we'll override some necessary methods. the first is onAttachedToWindow(), called when SlidingLayout is attached to window. At this point it has a Surface and will start drawing. Note that this function is guaranteed to be called before onDraw(). Here we set child views to our view and content variable:
    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();

        // Get our 2 children views
        menu = this.getChildAt(0);
        content = this.getChildAt(1);

        // Attach View.OnTouchListener
        content.setOnTouchListener(new OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                return onContentTouch(v, event);
            }
        });

        menu.setVisibility(View.GONE);
    }
    As you can see, we'll handle touching event (gesture) from user in this method to. There are 3 actions we must detect: ACTION_UP, ACTION_DOWN and ACTION_MOVE. When user drag in the content view, the main layout will be scrolled and the menu is displayed a part or whole. This is onContentTouch() method:
public boolean onContentTouch(View v, MotionEvent event) {
        // Do nothing if sliding is in progress
        if (currentMenuState == MenuState.HIDING || currentMenuState == MenuState.SHOWING)
            return false;

        // getRawX returns X touch point corresponding to screen
        // getX sometimes returns screen X, sometimes returns content View X
        int curX = (int) event.getRawX();
        int diffX = 0;

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

                prevX = curX;
                return true;

            case MotionEvent.ACTION_MOVE:
                // Set menu to Visible when user start dragging the content View
                if (!isDragging) {
                    isDragging = true;
                    menu.setVisibility(View.VISIBLE);
                }

                // How far we have moved since the last position
                diffX = curX - prevX;

                // Prevent user from dragging beyond border
                if (contentXOffset + diffX <= 0) {
                    // Don't allow dragging beyond left border
                    // Use diffX will make content cross the border, so only translate by -contentXOffset
                    diffX = -contentXOffset;
                } else if (contentXOffset + diffX > sldingLayoutWidth - menuRightMargin) {
                    // Don't allow dragging beyond menu width
                    diffX = sldingLayoutWidth - menuRightMargin - contentXOffset;
                }

                // Translate content View accordingly
                content.offsetLeftAndRight(diffX);

                contentXOffset += diffX;

                // Invalite this whole Slidinglayout, causing onLayout() to be called
                this.invalidate();

                prevX = curX;
                lastDiffX = diffX;
                return true;

            case MotionEvent.ACTION_UP:
                // Start scrolling
                // Remember that when content has a chance to cross left border, lastDiffX is set to 0
                if (lastDiffX > 0) {
                    // User wants to show menu
                    currentMenuState = MenuState.SHOWING;

                    // Start scrolling from contentXOffset
                    menuScroller.startScroll(contentXOffset, 0, menu.getLayoutParams().width - contentXOffset,
                            0, SLIDING_DURATION);
                } else if (lastDiffX < 0) {
                    // User wants to hide menu
                    currentMenuState = MenuState.HIDING;
                    menuScroller.startScroll(contentXOffset, 0, -contentXOffset,
                            0, SLIDING_DURATION);
                }

                // Begin querying
                menuHandler.postDelayed(menuRunnable, QUERY_INTERVAL);

                // Invalite this whole Slidinglayout, causing onLayout() to be called
                this.invalidate();

                // Done dragging
                isDragging = false;
                prevX = 0;
                lastDiffX = 0;
                return true;

            default:
                break;
        }
        return false;
    }
    So the main idea of sliding menu is to change contentXOffset and call offsetLeftAndRight for the content to move it.
    We create an enum to control sliding state:
private enum MenuState {
        HIDING, //slidingmenu is collapsing
        HIDDEN, //sliding menu is hidden
        SHOWING, //sliding menu is expanding
        SHOWN, //sliding menu is completely shown
    }
    Using it in toggleMenu() method, allow us to toggle menu:
public void toggleMenu() {
        // Do nothing if sliding is in progress
        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;
        }

        // Begin querying
        menuHandler.postDelayed(menuRunnable, QUERY_INTERVAL);

        // Invalite this whole SlidingLayout, causing onLayout() to be called
        this.invalidate();
    }
    Overriding onMeasure(), we compute menuRightMargin, this variable is the amount of right space the menu should not occupy. In this case, we want the menu to take up 85% amount of the screen width:
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        sldingLayoutWidth = MeasureSpec.getSize(widthMeasureSpec);
        //Sliding menu will take 85% screen size when completely shown
        menuRightMargin = sldingLayoutWidth * 15 / 100;
    }
    The last important method is onLayout(), this is called from layout when this view should assign a size and position to each of its children. This is where we position the menu and content view:
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        // True if SlidingLayout's size and position has changed
        // If true, calculate child views size
        if (changed) {
            // Note: LayoutParams are used by views to tell their parents how they want to be laid out
            // content View occupies the full height and width
            LayoutParams contentLayoutParams = (LayoutParams) content.getLayoutParams();
            contentLayoutParams.height = this.getHeight();
            contentLayoutParams.width = this.getWidth();

            // menu View occupies the full height, but certain width
            LayoutParams menuLayoutParams = (LayoutParams) menu.getLayoutParams();
            menuLayoutParams.height = this.getHeight();
            menuLayoutParams.width = this.getWidth() - menuRightMargin;
        }

        // Layout the child views    
        menu.layout(left, top, right - menuRightMargin, bottom);
        content.layout(left + contentXOffset, top, right + contentXOffset, bottom);
    }
    There are all important methods, adding some necessary features for our own purpose, we have full code for SlidingLayout class:
SlidingLayout.java
package info.devexchanges.slidingmenu;

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

public class SlidingLayout extends LinearLayout {

    // Duration of sliding animation, in miliseconds
    private static final int SLIDING_DURATION = 500;

    // Query Scroller every 16 miliseconds
    private static final int QUERY_INTERVAL = 16;

    // Sliding width
    int sldingLayoutWidth;

    // Sliding menu
    private View menu;

    // Main content
    private View content;

    // menu does not occupy some right space
    // This should be updated correctly later in onMeasure
    private static int menuRightMargin = 0;

    // The state of menu
    private enum MenuState {
        HIDING,
        HIDDEN,
        SHOWING,
        SHOWN,
    }

    // content will be layouted based on this X offset
    // Normally, contentXOffset = menu.getLayoutParams().width = this.getWidth - menuRightMargin
    private int contentXOffset;

    // menu is hidden when initializing
    private MenuState currentMenuState = MenuState.HIDDEN;

    // Scroller is used to facilitate animation
    private Scroller menuScroller = new Scroller(this.getContext(),
            new EaseInInterpolator());

    // Used to query Scroller about scrolling position
    // Note: The 3rd paramter to startScroll is the distance
    private Runnable menuRunnable = new MenuRunnable();
    private Handler menuHandler = new Handler();

    // Previous touch position
    int prevX = 0;

    // Is user dragging the content
    boolean isDragging = false;

    // Used to facilitate ACTION_UP 
    int lastDiffX = 0;

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

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

    // Overriding LinearLayout core methods
    // Ask all children to measure themselves and compute the measurement of this
    // layout based on the children
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        sldingLayoutWidth = MeasureSpec.getSize(widthMeasureSpec);
        //Sliding menu will take 85% screen size when completely shown
        menuRightMargin = sldingLayoutWidth * 15 / 100;
    }

    // This is called when SlidingLayout is attached to window
    // At this point it has a Surface and will start drawing. 
    // Note that this function is guaranteed to be called before onDraw
    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();

        // Get our 2 children views
        menu = this.getChildAt(0);
        content = this.getChildAt(1);

        // Attach View.OnTouchListener
        content.setOnTouchListener(new OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                return onContentTouch(v, event);
            }
        });

        menu.setVisibility(View.GONE);
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        // True if SlidingLayout's size and position has changed
        // If true, calculate child views size
        if (changed) {
            // Note: LayoutParams are used by views to tell their parents how they want to be laid out
            // content View occupies the full height and width
            LayoutParams contentLayoutParams = (LayoutParams) content.getLayoutParams();
            contentLayoutParams.height = this.getHeight();
            contentLayoutParams.width = this.getWidth();

            // menu View occupies the full height, but certain width
            LayoutParams menuLayoutParams = (LayoutParams) menu.getLayoutParams();
            menuLayoutParams.height = this.getHeight();
            menuLayoutParams.width = this.getWidth() - menuRightMargin;
        }

        // Layout the child views    
        menu.layout(left, top, right - menuRightMargin, bottom);
        content.layout(left + contentXOffset, top, right + contentXOffset, bottom);
    }

    // Custom methods for SlidingLayout
    // Used to show/hide menu accordingly
    public void toggleMenu() {
        // Do nothing if sliding is in progress
        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;
        }

        // Begin querying
        menuHandler.postDelayed(menuRunnable, QUERY_INTERVAL);

        // Invalite this whole SlidingLayout, causing onLayout() to be called
        this.invalidate();
    }

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

    // Adjust content View position to match sliding animation
    private void adjustContentPosition(boolean isScrolling) {
        int scrollerXOffset = menuScroller.getCurrX();

        // Translate content View accordingly
        content.offsetLeftAndRight(scrollerXOffset - contentXOffset);

        contentXOffset = scrollerXOffset;

        // Invalite this whole Slidinglayout, causing onLayout() to be called
        this.invalidate();

        // Check if animation is in progress
        if (isScrolling)
            menuHandler.postDelayed(menuRunnable, QUERY_INTERVAL);
        else
            this.onMenuSlidingComplete();
    }

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

    // Make scrolling more natural. Move more quickly at the end
    protected class EaseInInterpolator implements Interpolator {
        @Override
        public float getInterpolation(float t) {
            return (float) Math.pow(t - 1, 5) + 1;
        }

    }

    // Is menu completely shown
    public boolean isMenuShown() {
        return currentMenuState == MenuState.SHOWN;
    }

    // Handle touch event on content View
    public boolean onContentTouch(View v, MotionEvent event) {
        // Do nothing if sliding is in progress
        if (currentMenuState == MenuState.HIDING || currentMenuState == MenuState.SHOWING)
            return false;

        // getRawX returns X touch point corresponding to screen
        // getX sometimes returns screen X, sometimes returns content View X
        int curX = (int) event.getRawX();
        int diffX = 0;

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

                prevX = curX;
                return true;

            case MotionEvent.ACTION_MOVE:
                // Set menu to Visible when user start dragging the content View
                if (!isDragging) {
                    isDragging = true;
                    menu.setVisibility(View.VISIBLE);
                }

                // How far we have moved since the last position
                diffX = curX - prevX;

                // Prevent user from dragging beyond border
                if (contentXOffset + diffX <= 0) {
                    // Don't allow dragging beyond left border
                    // Use diffX will make content cross the border, so only translate by -contentXOffset
                    diffX = -contentXOffset;
                } else if (contentXOffset + diffX > sldingLayoutWidth - menuRightMargin) {
                    // Don't allow dragging beyond menu width
                    diffX = sldingLayoutWidth - menuRightMargin - contentXOffset;
                }

                // Translate content View accordingly
                content.offsetLeftAndRight(diffX);

                contentXOffset += diffX;

                // Invalite this whole Slidinglayout, causing onLayout() to be called
                this.invalidate();

                prevX = curX;
                lastDiffX = diffX;
                return true;

            case MotionEvent.ACTION_UP:
                // Start scrolling
                // Remember that when content has a chance to cross left border, lastDiffX is set to 0
                if (lastDiffX > 0) {
                    // User wants to show menu
                    currentMenuState = MenuState.SHOWING;

                    // Start scrolling from contentXOffset
                    menuScroller.startScroll(contentXOffset, 0, menu.getLayoutParams().width - contentXOffset,
                            0, SLIDING_DURATION);
                } else if (lastDiffX < 0) {
                    // User wants to hide menu
                    currentMenuState = MenuState.HIDING;
                    menuScroller.startScroll(contentXOffset, 0, -contentXOffset,
                            0, SLIDING_DURATION);
                }

                // Begin querying
                menuHandler.postDelayed(menuRunnable, QUERY_INTERVAL);

                // Invalite this whole Slidinglayout, causing onLayout() to be called
                this.invalidate();

                // Done dragging
                isDragging = false;
                prevX = 0;
                lastDiffX = 0;
                return true;

            default:
                break;
        }
        return false;
    }
}

Usage in interface (Activity)

    In the Activity layout, adding SlidingLayout as the root container, the menu view certainly is a ListView and the content view is an empty ViewGroup, we will replace Fragments to it then. The menu icon is located in Toolbar:
activity_main.xml
<info.devexchanges.slidingmenu.SlidingLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/sliding_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <!-- This holds our menu -->
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <ListView
            android:id="@+id/activity_main_menu_listview"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="#ffb366"
            android:scrollbars="none" />
    </LinearLayout>

    <!-- This holds our content-->
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="@color/colorPrimary"
            android:orientation="horizontal"
            app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
            app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

            <ImageView
                android:id="@+id/menu_icon"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:contentDescription="@string/app_name"
                android:onClick="toggleMenu"
                android:src="@drawable/menu" />

            <TextView
                android:id="@+id/title"
                style="@style/TextAppearance.Widget.AppCompat.Toolbar.Title"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginLeft="@dimen/activity_horizontal_margin"
                android:layout_marginStart="@dimen/activity_horizontal_margin"
                android:gravity="center"
                android:textColor="@android:color/white" />

        </android.support.v7.widget.Toolbar>

        <!-- Fragments container layout -->
        <FrameLayout
            android:id="@+id/activity_main_content_fragment"
            android:layout_width="match_parent"
            android:layout_height="match_parent">

        </FrameLayout>
    </LinearLayout>
</info.devexchanges.slidingmenu.SlidingLayout>
    As you can see, I put an ImageView and a TextView inside Toolbar. They work as a toggle menu button and the title of screens.

Programmatically code

    Your Activity must extend from AppCompatActivity, there is nothing too special in code, we set adapter for the ListView (as the menu view), handling menu item click event by replace the corresponding Fragment to the container layout:
MainActivity.java
package info.devexchanges.slidingmenu;

import android.annotation.SuppressLint;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {
    // The SlidingLayout which will hold both the sliding menu and our main content
    // Main content will holds our Fragment respectively
    SlidingLayout slidingLayout;

    // ListView menu
    private ListView listMenu;
    private String[] listMenuItems;

    private Toolbar toolbar;
    private TextView title; //page title
    private ImageView btMenu; // Menu button
    private Fragment currentFragment;

    @SuppressLint("SetTextI18n")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Inflate the mainLayout
        setContentView(R.layout.activity_main);
        slidingLayout = (SlidingLayout) findViewById(R.id.sliding_layout);
        toolbar = (Toolbar) findViewById(R.id.toolbar);
        title = (TextView) findViewById(R.id.title);
        setSupportActionBar(toolbar);

        // Init menu
        listMenuItems = getResources().getStringArray(R.array.menu_items);
        listMenu = (ListView) findViewById(R.id.activity_main_menu_listview);
        listMenu.setAdapter(new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, listMenuItems));
        listMenu.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                onMenuItemClick(parent, view, position, id);
            }

        });

        // handling menu button event
        btMenu = (ImageView) findViewById(R.id.menu_icon);
        btMenu.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // Show/hide the menu
                toggleMenu(v);
            }
        });

        // Replace fragment main when activity start
        FragmentManager fm = MainActivity.this.getSupportFragmentManager();
        FragmentTransaction ft = fm.beginTransaction();

        MainFragment fragment = new MainFragment();
        ft.add(R.id.activity_main_content_fragment, fragment);
        ft.commit();

        currentFragment = fragment;
        title.setText("Sliding Menu like Facebook");
    }

    public void toggleMenu(View v) {
        slidingLayout.toggleMenu();
    }

    // Perform action when a menu item is clicked
    private void onMenuItemClick(AdapterView<?> parent, View view, int position, long id) {
        FragmentManager fm = getSupportFragmentManager();
        FragmentTransaction ft = fm.beginTransaction();
        Fragment fragment;

        if (position == 0) {
            fragment = new MainFragment();
            title.setText("Main Screen");
        } else if (position == 1) {
            fragment = new ListViewFragment();
            title.setText("ListView Fragment");
        } else if (position == 2) {
            fragment = new TextViewFragment();
            Bundle args = new Bundle();
            args.putString("KEY_STRING", "This is a TextView in the Fragment");
            fragment.setArguments(args);
            title.setText("TextView Fragment");
        } else {
            fragment = new DummyFragment();
            title.setText("Blank Fragment");
        }

        if(!fragment.getClass().equals(currentFragment.getClass())) {
            // Replace current fragment by this new one
            ft.replace(R.id.activity_main_content_fragment, fragment);
            ft.commit();

            currentFragment = fragment;
        }

        // Hide menu anyway
        slidingLayout.toggleMenu();

    }

    @Override
    public void onBackPressed() {
        if (slidingLayout.isMenuShown()) {
            slidingLayout.toggleMenu();
        } else {
            super.onBackPressed();
        }
    }

    @Override
    protected void onStart() {
        super.onStart();
        getSupportActionBar().setTitle("");
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return super.onCreateOptionsMenu(menu);
    }
}
     When running app, you'll have this output:

Coclusions and references

    With ListViewFragment, TextViewFragments and some another necessary files, you can view them on @Github. Through this post, I hope that you can be learned about making a complicated custom view (the sliding menu). This menu type is better Navigation Drawer in Android SDK, the application looks smoother in use.
    References:

Android - Create Sliding Panel like Gmail app on Tablet

    In my previous post, I have presented the "ListView with Letter Icon" like Gmail app. Therefore, in Tablet, this app also has an interesting UI with "partial sliding panel":
    This is not NavigationDrawer, it is SlidingPaneLayout. In this post, I will provide some solutions to custom this widget to make a layout like Gmail!

Original Sliding Panel

    By original, this widget has 2 children layouts, the first one is left panel and the other one is the main panel. A simple layout will be like this:
activity_main.xml
<android.support.v4.widget.SlidingPaneLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/sliding_pane_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    
    <TextView
        android:layout_width="230dp"
        android:layout_height="match_parent"
        android:background="@android:color/holo_blue_dark"
        android:text="Panel 1" />

    
    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@android:color/holo_green_dark"
        android:text="Panel 2" />
</android.support.v4.widget.SlidingPaneLayout>
    After running, we have this result:

NOTE: In some devices, when the left panel expanded, the main layout may be turned to gray:
    To avoiding this matter, please add this code to change the fade color to transperant:
SlidingPaneLayout slidingPaneLayout = (SlidingPaneLayout) findViewById(R.id.sliding_pane_layout);
assert slidingPaneLayout != null;
slidingPaneLayout.setSliderFadeColor(Color.TRANSPARENT);

Partial Sliding Panel

Now we'll make the main panel partially visible when collapsed. Very simple: adding margin to the main panel:
activity_main.xml
<android.support.v4.widget.SlidingPaneLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/sliding_pane_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:layout_width="250dp"
        android:layout_height="match_parent"
        android:background="@android:color/holo_blue_dark"
        android:text="Panel 1" />

    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginLeft="60dp"
        android:background="@android:color/holo_green_dark"
        android:text="Panel 2" />
</android.support.v4.widget.SlidingPaneLayout>
    We'll have this result:

Handling Panel expand/collapse event

    To handling the SlidingPanelLayout event, make your Activity/Fragment implements SlidingPaneLayout.PanelSlideListener and overriding these 3 methods:
  • onPanelOpened(): Called when the left panel completely open.
  • onPanelClosed(): Called when the lef panel completely collapsed. The panel is now guaranteed to be interactive. It may now obscure other views in the layout.
  • onPanelSlide():Called when a sliding panel's position changes.

Complex data: an example

    Now, I will provide a project with 2 SlidingPanelLayout children is ListViews. The activity layout wille be like:
activity_main.xml
<android.support.v4.widget.SlidingPaneLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/sliding_pane_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout
        android:layout_width="250dp"
        android:layout_height="match_parent"
        android:background="#66b3ff"
        android:orientation="vertical">

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="#0000ff"
            android:gravity="center"
            android:padding="10dp"
            android:text="Continents"
            android:textColor="#ffffff" />

        <ListView
            android:id="@+id/left_list"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />

    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginLeft="60dp"
        android:orientation="vertical">

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="#00d0f0"
            android:gravity="center"
            android:padding="10dp"
            android:text="Countries"
            android:textColor="#ffffff" />

        <ListView
            android:id="@+id/main_list"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="#0099C2" />

    </LinearLayout>
</android.support.v4.widget.SlidingPaneLayout>
    In the programmatically code, set adapter for each ListView, handling their item click event and show/hide the left panel ListView when it's expand/collapse, we have this full code:
MainActivity.java
package info.devexchanges.slidingpanel;

import android.graphics.Color;
import android.support.v4.widget.SlidingPaneLayout;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity implements SlidingPaneLayout.PanelSlideListener {

    private ListView leftListView;
    private ListView mainListView;
    private String[] asiaCountries;
    private String[] europeCountries;
    private String[] africaCountries;
    private String[] continents;
    private static final String[] NO_DATA = {};
    private ArrayAdapter<String> mainPanelAdapter;
    private String TAG = MainActivity.class.getSimpleName();

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

        leftListView = (ListView) findViewById(R.id.left_list);
        mainListView = (ListView) findViewById(R.id.main_list);

        SlidingPaneLayout slidingPaneLayout = (SlidingPaneLayout) findViewById(R.id.sliding_pane_layout);
        assert slidingPaneLayout != null;
        slidingPaneLayout.setPanelSlideListener(this);
        slidingPaneLayout.setSliderFadeColor(Color.TRANSPARENT);

        //get string arrays resource
        asiaCountries = getResources().getStringArray(R.array.asia);
        europeCountries = getResources().getStringArray(R.array.europe);
        africaCountries = getResources().getStringArray(R.array.africa);
        continents = getResources().getStringArray(R.array.continent);

        //set listviews adapter
        ArrayAdapter<String> leftPaneAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, continents);
        leftListView.setAdapter(leftPaneAdapter);
        mainPanelAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, asiaCountries);
        mainListView.setAdapter(mainPanelAdapter);

        //handling left panel listview item click event
        leftListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                if (position == 0) {
                    setMainAdapter(asiaCountries);
                } else if (position == 1) {
                    setMainAdapter(europeCountries);
                } else if (position == 2) {
                    setMainAdapter(africaCountries);
                } else {
                    setMainAdapter(NO_DATA);
                    Toast.makeText(MainActivity.this, "No data!", Toast.LENGTH_SHORT).show();
                }
            }
        });

        //handling main panel listview item click event
        mainListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                String item = (String) parent.getItemAtPosition(position);
                Toast.makeText(MainActivity.this, "You selectd: " + item, Toast.LENGTH_SHORT).show();
            }
        });
    }

    private void setMainAdapter(String[] strings) {
        mainPanelAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, strings);
        mainListView.setAdapter(mainPanelAdapter);
    }

    @Override
    public void onPanelSlide(View panel, float slideOffset) {
        Log.i(TAG, "onPanelSlide: " + slideOffset);
    }

    @Override
    public void onPanelOpened(View panel) {
        Log.i(TAG, "onPanelOpened");
        leftListView.setVisibility(View.VISIBLE);
    }

    @Override
    public void onPanelClosed(View panel) {
        Log.i(TAG, "onPanelClosed");
        leftListView.setVisibility(View.GONE);
    }
}
     And this is the final result:

Conclusions

Through this post, I hope readers can learned once more widget in Android SDK to make a interesting layout (like Gmail application). You can take a glance at my previous post (about making ListView with letter icon on the left side). Moreover, let subscribe my blog to get newest tutorials. Finally, you can download full project on @Github.

Android - Make Sliding Menu by Navigation Drawer with Material Design style

    NavigationDrawer, from appearing, always become a most interesting widget in Android SDK. Over time with API levels, it has been designed better. Now, with Material Design, navigation drawer gives smooth animation when you swipe across the screen from left edge. You may see this and think about how to implement same functionality in older versions, but now not to worry because using android appcompat support library, we can give same effect to older versions of android app.
    In Material Design, it's layout be come more flexible with animations and developers can customizing it's easily with our own styles. For example, this is toggle menu animation:
In this post, I will make a NavigationDrawer with Toolbar in a simple project. By this, you can deep understanding the way how to implement it.

Create main activity layout

    In running activity, we have a DrawerLayout at root. It's has 2 children layouts (main layout and sliding panel). Please look at this layout structure:
    So, we have a simple activity layout below:
    Note: In this layout, I put Toolbar inside DrawerLayout, so this NavigationDrawer will occult Toolbar when it's appear:
If you want it appear below Toolbar, please include Toolbar layout outside DrawerLayout and output will be like this:

Making Sliding Panel

    As you can see above, in Sliding Panel, we have a ListView. We must setup it's components. In this project, each row is a SocialNetwork name and icon. Layout for ListView row:
   Create a model (Java object):
package devexchanges.info.navigationdrawer;

/**
 * Created by Hong Thai.
 */
public class SocialNetwork {
    private int imageId;
    private int bigImageId;
    private String name;
    private String country;

    public SocialNetwork(int imageId, int bigImageId, String name, String country) {
        this.country = country;
        this.bigImageId = bigImageId;
        this.imageId = imageId;
        this.name = name;
    }

    public int getImageId() {
        return imageId;
    }

    public int getBigImageId() {
        return bigImageId;
    }

    public String getCountry() {
        return country;
    }

    public String getName() {
        return name;
    }
}
Now, we create a customizing a ListView adapter extends from ArrayAdapter<T>, in this, I use a ViewHolder class to make it's view more smoothly. Source code for adapter:
package devexchanges.info.navigationdrawer;

import android.app.Activity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;

import java.util.ArrayList;

import devexchanges.info.materialdesignnavigationdrawer.R;

public class ListViewAdapter extends ArrayAdapter<Socialnetwork> {

    private MainActivity activity;
    private ArrayList<Socialnetwork> socialNetworks;

    public ListViewAdapter(MainActivity activity, int resource, ArrayList<Socialnetwork> objects) {
        super(activity, resource, objects);
        this.activity = activity;
        this.socialNetworks = objects;
    }

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

        ViewHolder holder = null;
        LayoutInflater inflater = (LayoutInflater) activity
                .getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
        // If holder not exist then locate all view from UI file.
        if (convertView == null) {
            // inflate UI from XML file
            convertView = inflater.inflate(R.layout.item_listview, parent, false);
            // get all UI view
            holder = new ViewHolder(convertView);
            // set tag for holder
            convertView.setTag(holder);
        } else {
            // if holder created, get tag from view
            holder = (ViewHolder) convertView.getTag();
        }

        holder.name.setText(getItem(position).getName());
        holder.icon.setImageResource(getItem(position).getImageId());

        //handling each item on click
        //update main layout by this action
        convertView.setOnClickListener(onClickListener(position));

        return convertView;
    }

    private View.OnClickListener onClickListener(final int position) {
        return new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                activity.updateMainLayout(getItem(position));
            }
        };
    }

    private class ViewHolder {
        private ImageView icon;
        private TextView name;

        public ViewHolder(View v) {
            icon = (ImageView) v.findViewById(R.id.icon);
            name = (TextView) v.findViewById(R.id.name);
        }
    }
}
    In activity, set adapter for ListView when initializing Sliding Panel. Set a listener to be notified of drawer events though initDrawerlayout() method and call it in onCreate():
private void initDrawerLayout() {
        setListViewData();
        setListViewHeader();
        //Mount listview with adapter
        adapter = new ListViewAdapter(this, R.layout.item_listview, socialNetworks);
        listView.setAdapter(adapter);

        drawerToggle = new ActionBarDrawerToggle(this, drawerLayout, toolbar,
                R.string.drawer_open, R.string.drawer_close) {

            @Override
            public void onDrawerClosed(View drawerView) {
                super.onDrawerClosed(drawerView);
            }

            @Override
            public void onDrawerOpened(View drawerView) {
                super.onDrawerOpened(drawerView);

            }
        };
        drawerLayout.setDrawerListener(drawerToggle);
    }
    After that, synchronize the state of the drawer indicator/affordance with the linked DrawerLayout by invoke syncState(). I overrided onPostCreate() and onConfigurationChanged() methods:
@Override
    protected void onPostCreate(Bundle savedInstanceState) {
        super.onPostCreate(savedInstanceState);
        drawerToggle.syncState();
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        drawerToggle.onConfigurationChanged(newConfig);
    }
    We also add a header for ListView to make our Sliding Panel more beautiful (like GooglePlus app):
 private void setListViewHeader() {
        LayoutInflater inflater = getLayoutInflater();
        View header = inflater.inflate(R.layout.header_listview, listView, false);
        listView.addHeaderView(header, null, false);
    }

Coding Main Layout

    As description above (ListViewAdapter class), when click at each Sliding Panel item, we will update main layout by replace a Fragment to Activity. Put this code to main activity:
    /**
     * Replace fragment to Main layout
     * @param socialNetwork
     */
    public void updateMainLayout(SocialNetwork socialNetwork) {
        FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();

        transaction.replace(R.id.container, ContentFragment.newInstance(socialNetwork));
        transaction.commit();

        //close navigation drawer after replace fragment
        drawerLayout.closeDrawers();
    }
    And source for ContentFragment is simple. Put/get data by a Bundle object and update data to views by getArguments():
package devexchanges.info.navigationdrawer;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

import devexchanges.info.materialdesignnavigationdrawer.R;

public class ContentFragment extends Fragment {

    private TextView socialNetworkName;
    private TextView country;
    private ImageView image;

    public static ContentFragment newInstance(SocialNetwork nw) {
        Bundle args = new Bundle();
        ContentFragment fragment = new ContentFragment();
        args.putString("SN_NAME", nw.getName());
        args.putInt("SN_LOGO", nw.getBigImageId());
        args.putString("SN_COUNTRY", nw.getCountry());
        fragment.setArguments(args);
        return fragment;
    }

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

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        socialNetworkName = (TextView)view.findViewById(R.id.social_network);
        country = (TextView)view.findViewById(R.id.country);
        image = (ImageView)view.findViewById(R.id.icon);

        updateData();
    }

    private void updateData() {
        socialNetworkName.setText(getArguments().getString("SN_NAME"));
        image.setImageResource(getArguments().getInt("SN_LOGO"));
        country.setText(getArguments().getString("SN_COUNTRY"));
    }
}
Coming here, we have complete our project core. This is full code of main activity (the most important file):
package devexchanges.info.navigationdrawer;

import android.support.v4.app.FragmentTransaction;
import android.content.res.Configuration;
import android.os.Bundle;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.View;
import android.widget.ListView;

import java.util.ArrayList;

import devexchanges.info.materialdesignnavigationdrawer.R;

public class MainActivity extends AppCompatActivity {

    private Toolbar toolbar;
    private DrawerLayout drawerLayout;
    private ActionBarDrawerToggle drawerToggle;
    private ListView listView;
    private ArrayList<Socialnetwork> socialNetworks;
    private ListViewAdapter adapter;


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

        socialNetworks = new ArrayList<>();
        findViewById();
        setSupportActionBar(toolbar);

        initDrawerLayout();
    }

    private void findViewById() {
        listView = (ListView) findViewById(R.id.list);
        toolbar = (Toolbar) findViewById(R.id.toolbar);
        drawerLayout = (DrawerLayout) findViewById(R.id.drawerLayout);
    }

    private void initDrawerLayout() {
        setListViewData();
        setListViewHeader();
        //Mount listview with adapter
        adapter = new ListViewAdapter(this, R.layout.item_listview, socialNetworks);
        listView.setAdapter(adapter);

        drawerToggle = new ActionBarDrawerToggle(this, drawerLayout, toolbar,
                R.string.drawer_open, R.string.drawer_close) {

            @Override
            public void onDrawerClosed(View drawerView) {
                super.onDrawerClosed(drawerView);
            }

            @Override
            public void onDrawerOpened(View drawerView) {
                super.onDrawerOpened(drawerView);

            }
        };
        drawerLayout.setDrawerListener(drawerToggle);
    }

    private void setListViewHeader() {
        LayoutInflater inflater = getLayoutInflater();
        View header = inflater.inflate(R.layout.header_listview, listView, false);
        listView.addHeaderView(header, null, false);
    }

    private void setListViewData() {
        socialNetworks.add(new SocialNetwork(R.mipmap.zalo_small, R.mipmap.zalo_big, "Zalo", "VIETNAM"));
        socialNetworks.add(new SocialNetwork(R.mipmap.fb_small, R.mipmap.fb_big, "Facebook", "USA"));
        socialNetworks.add(new SocialNetwork(R.mipmap.tw_small, R.mipmap.tw_big, "Twitter", "USA"));
        socialNetworks.add(new SocialNetwork(R.mipmap.pin_small, R.mipmap.pin_big, "Pinterest", "USA"));
        socialNetworks.add(new SocialNetwork(R.mipmap.gp_small, R.mipmap.gp_big, "Google+", "USA"));
        socialNetworks.add(new SocialNetwork(R.mipmap.baidu_small, R.mipmap.baidu_big, "Baidu", "CHINA"));
    }

    @Override
    protected void onPostCreate(Bundle savedInstanceState) {
        super.onPostCreate(savedInstanceState);
        drawerToggle.syncState();
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        drawerToggle.onConfigurationChanged(newConfig);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.menu_main, menu);

        return super.onCreateOptionsMenu(menu);
    }

    /**
     * Replace fragment to Main layout
     * @param socialNetwork
     */
    public void updateMainLayout(SocialNetwork socialNetwork) {
        FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();

        transaction.replace(R.id.container, ContentFragment.newInstance(socialNetwork));
        transaction.commit();

        //close navigation drawer after replace fragment
        drawerLayout.closeDrawers();
    }
}

Some necessary features/layouts

    ContentFragment layout in xml, display ListView elements details:
    Layout for ListView header:
    Customizing a theme based on "Theme.Appcompat.Light.NoActionBar" and apply for whole project:
    Toolbar layout:
    Colors resource:
    Remember add support libraries dependency in your local build.gradle file:
compile 'com.android.support:appcompat-v7:22.2.0'
compile 'com.android.support:support-v4:22.2.0'

Running application