Android Navigation Drawer

The navigation drawer is a panel that displays the app’s main navigation 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, while at the top level of the app, the user touches the app icon in the action bar. This tutorial guides you on how to create a navigable drawer application.

Step 1:
Create a new Android application using application name: "Navigation Drawer" and package name: "com.javahelps.navigationdrawer".


Step 2:
Select the "Navigation Drawer Activity" as the default activity.



Step 3: (Optional)
If you want to test the default template, run the project.


Step 4:
To change the default theme color of the application, change the values in values/colors.xml file.
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="colorPrimary">#e51717</color>
    <color name="colorPrimaryDark">#b90808</color>
    <color name="colorAccent">#e51717</color>
    <color name="statusBarColor">#b20909</color>
</resources>
In these set of colors, the colorAccent is the color of FloatingButton. Others are used for Title bar and other UI views.

Step 5:
Change the gradient of the Navigation Drawer by modifying the drawable/side_nav_bar.xml file.
To generate your favorite gradient, you can use this online tool: Online Gradient Generator
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" >
    <gradient
        android:type="linear"
        android:centerX="50%"
        android:startColor="#FFFF0000"
        android:centerColor="#FF800000"
        android:endColor="#FFff0000"
        android:angle="135"/>
</shape>

Step 6:
Create two new Blank Fragments named "HomeFragment" and "SettingsFragment".


Step 7:
Modify the content of the layout/fragment_home.xml as shown below.
<?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"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:context="com.javahelps.navigationdrawer.HomeFragment">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Home" />

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_alignParentRight="true"
        android:layout_margin="@dimen/fab_margin"
        android:src="@android:drawable/ic_input_add" />
</RelativeLayout>
In this code a TextView is used to show that this is the HomeFragment and a FloatingActionButton is used as an additional view. According to your purpose, you can change these user-interface components.

Step 8:
Modify the layout/fragment_settings.xml as shown below. This layout has a single TextView with a text "Settings".
<?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"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:context="com.javahelps.navigationdrawer.SettingsFragment">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Settings" />
</RelativeLayout>

Step 9:
Modify the layout/app_bar_main.xml as shown below. This layout is used to decorate the fragments using an overlaying ActionBar.
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout 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"
    android:fitsSystemWindows="true"
    tools:context=".MainActivity">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <android.support.design.widget.AppBarLayout
            android:id="@+id/actionBar"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:theme="@style/AppTheme.AppBarOverlay">

            <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                android:background="?attr/colorPrimary"
                app:popupTheme="@style/AppTheme.PopupOverlay" />

        </android.support.design.widget.AppBarLayout>

        <FrameLayout
            android:id="@+id/content"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_below="@id/actionBar" />

    </RelativeLayout>
</android.support.design.widget.CoordinatorLayout>
CoordinatorLayout is recommended as the parent layout in-order to support the FloatingActionButton and Snackbar (which is used later in this tutorial).

Step 10:
Delete the layout/content_main.xml, which is no longer needed.

Step 11:
layout/nav_header_main.xml is the layout which defines the header part of Navigation Drawer. Modify it using any desired icon and content.
<?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="@dimen/nav_header_height"
    android:background="@drawable/side_nav_bar"
    android:gravity="bottom"
    android:orientation="vertical"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:theme="@style/ThemeOverlay.AppCompat.Dark">

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:paddingTop="@dimen/nav_header_vertical_spacing"
        android:src="@drawable/logo" />

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingTop="@dimen/nav_header_vertical_spacing"
        android:text="Java Helps"
        android:textAppearance="@style/TextAppearance.AppCompat.Body1"
        android:textStyle="bold" />

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="admin@javahelps.com" />

</LinearLayout>
In this code, I am using logo.png as the icon. To use any such a third party png file, you need to import it in the drawable folder.

Step 12:
Change the content of menu/activity_main_drawer.xml as given below. The original activity_main_drawer.xml contains multiple options but since we have only two Fragments, two options are enough. The last item Communicate is left for your reference. If you are not going to use it, feel free to remove it.
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">

    <group android:checkableBehavior="single">
        <item
            android:id="@+id/nav_home"
            android:icon="@android:drawable/ic_menu_agenda"
            android:title="Home" />
        <item
            android:id="@+id/nav_settings"
            android:icon="@android:drawable/ic_menu_manage"
            android:title="Settings" />
    </group>

    <item android:title="Communicate">
        <menu>
            <item
                android:id="@+id/nav_share"
                android:icon="@android:drawable/ic_menu_share"
                android:title="Share" />
            <item
                android:id="@+id/nav_send"
                android:icon="@android:drawable/ic_menu_send"
                android:title="Send" />
        </menu>
    </item>
</menu>

Step 13:
Create a new interface "OnFragmentInteractionListener".
package com.javahelps.navigationdrawer;

import android.net.Uri;

public interface OnFragmentInteractionListener {
    void onFragmentInteraction(Uri uri);

}
This interface will be implemented by the MainActivity to support interaction from Fragment.

Step 14:
Modify the onAttach(Activity activity) method of SettingsFragment.java and HomeFragment.java as shown below.
@Override
public void onAttach(Context context) {
    super.onAttach(context);
    try {
        mListener = (OnFragmentInteractionListener) context;
    } catch (ClassCastException e) {
        throw new ClassCastException(context.toString()
                + " must implement OnFragmentInteractionListener");
    }
}
onAttach(Activity activity) method is deprecated in API 23, so the new onAttach(Context context) is used in this code.

Step 15:
Delete the "OnFragmentInteractionListener" interface from the SettingsFragment.java and HomeFragment.java.
/**
 * This interface must be implemented by activities that contain this
 * fragment to allow an interaction in this fragment to be communicated
 * to the activity and potentially other fragments contained in that
 * activity.
 * <p/>
 * See the Android Training lesson <a href=
 * "http://developer.android.com/training/basics/fragments/communicating.html"
 * >Communicating with Other Fragments</a> for more information.
 */
public interface OnFragmentInteractionListener {
    // TODO: Update argument type and name
    public void onFragmentInteraction(Uri uri);
}
After the modification, the SettingsFragment.java should look like this:
package com.javahelps.navigationdrawer;

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


public class SettingsFragment extends Fragment {
    // TODO: Rename parameter arguments, choose names that match
    // the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
    private static final String ARG_PARAM1 = "param1";
    private static final String ARG_PARAM2 = "param2";

    // TODO: Rename and change types of parameters
    private String mParam1;
    private String mParam2;

    private OnFragmentInteractionListener mListener;

    /**
     * Use this factory method to create a new instance of
     * this fragment using the provided parameters.
     *
     * @param param1 Parameter 1.
     * @param param2 Parameter 2.
     * @return A new instance of fragment SettingsFragment.
     */
    // TODO: Rename and change types and number of parameters
    public static SettingsFragment newInstance(String param1, String param2) {
        SettingsFragment fragment = new SettingsFragment();
        Bundle args = new Bundle();
        args.putString(ARG_PARAM1, param1);
        args.putString(ARG_PARAM2, param2);
        fragment.setArguments(args);
        return fragment;
    }

    public SettingsFragment() {
        // Required empty public constructor
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (getArguments() != null) {
            mParam1 = getArguments().getString(ARG_PARAM1);
            mParam2 = getArguments().getString(ARG_PARAM2);
        }
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_settings, container, false);
    }

    // TODO: Rename method, update argument and hook method into UI event
    public void onButtonPressed(Uri uri) {
        if (mListener != null) {
            mListener.onFragmentInteraction(uri);
        }
    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        try {
            mListener = (OnFragmentInteractionListener) context;
        } catch (ClassCastException e) {
            throw new ClassCastException(context.toString()
                    + " must implement OnFragmentInteractionListener");
        }
    }

    @Override
    public void onDetach() {
        super.onDetach();
        mListener = null;
    }
}

Step 16:
Override the onViewCreated method in HomeFragment class and modify it as shown below.
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);

    FloatingActionButton fab = (FloatingActionButton) view.findViewById(R.id.fab);
    fab.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                    .setAction("Action", null).show();
        }
    });
}
In this code, we find the FloatingActionButton and set an onClickListener to it.

Snackbar is used to show a message in this code. If you are new to Snackbar, here is the quick introduction of Snackbar.
Snackbars provide lightweight feedback about an operation. Snackbars are shown on the bottom of the screen and contain text with an optional single action. They automatically time out after the given time length by animating off the screen. In addition, users can swipe them away before the timeout.
After the modification, the HomeFragment.java should look like this:
package com.javahelps.navigationdrawer;

import android.content.Context;
import android.net.Uri;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;


public class HomeFragment extends Fragment {
    // TODO: Rename parameter arguments, choose names that match
    // the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
    private static final String ARG_PARAM1 = "param1";
    private static final String ARG_PARAM2 = "param2";

    // TODO: Rename and change types of parameters
    private String mParam1;
    private String mParam2;

    private OnFragmentInteractionListener mListener;

    /**
     * Use this factory method to create a new instance of
     * this fragment using the provided parameters.
     *
     * @param param1 Parameter 1.
     * @param param2 Parameter 2.
     * @return A new instance of fragment HomeFragment.
     */
    // TODO: Rename and change types and number of parameters
    public static HomeFragment newInstance(String param1, String param2) {
        HomeFragment fragment = new HomeFragment();
        Bundle args = new Bundle();
        args.putString(ARG_PARAM1, param1);
        args.putString(ARG_PARAM2, param2);
        fragment.setArguments(args);
        return fragment;
    }

    public HomeFragment() {
        // Required empty public constructor
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (getArguments() != null) {
            mParam1 = getArguments().getString(ARG_PARAM1);
            mParam2 = getArguments().getString(ARG_PARAM2);
        }
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_home, container, false);
    }

    // TODO: Rename method, update argument and hook method into UI event
    public void onButtonPressed(Uri uri) {
        if (mListener != null) {
            mListener.onFragmentInteraction(uri);
        }
    }

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        FloatingActionButton fab = (FloatingActionButton) view.findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                        .setAction("Action", null).show();
            }
        });
    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        try {
            mListener = (OnFragmentInteractionListener) context;
        } catch (ClassCastException e) {
            throw new ClassCastException(context.toString()
                    + " must implement OnFragmentInteractionListener");
        }
    }

    @Override
    public void onDetach() {
        super.onDetach();
        mListener = null;
    }
}

Step 17:
Open the MainActivity.java, implement the OnFragmentInteractionListener interface and override the onFragmentInteraction method. If you need to receive any information from the Fragments, you can use this method.
public class MainActivity extends AppCompatActivity
        implements NavigationView.OnNavigationItemSelectedListener, OnFragmentInteractionListener {
    ...
    @Override
    public void onFragmentInteraction(Uri uri) {

    }
}

Step 18:
Modify the onCreate method as given below.
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);

    DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
    ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
            this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
    drawer.setDrawerListener(toggle);
    toggle.syncState();

    NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
    navigationView.setNavigationItemSelectedListener(this);

    // Set the home as default
    Fragment fragment = new HomeFragment();
    FragmentManager fragmentManager = getSupportFragmentManager();
    fragmentManager.beginTransaction()
            .replace(R.id.content, fragment)
            .commit();
}
In this code the FloatingActionButton related code is removed since the button is moved to the HomeFragment. HomeFragment is assigned as the default fragment at the end of onCreate method.
The Fragment and FragmentManager are available in the android.support.v4.app.

Step 19:
Modify the onNavigationItemSelected method as shown below.
public boolean onNavigationItemSelected(MenuItem item) {
    // Handle navigation view item clicks here.
    int id = item.getItemId();

    // Create a new fragment and specify the planet to show based on position
    Fragment fragment;

    if (id == R.id.nav_settings) {
        // Handle the settings action
        fragment = new SettingsFragment();
    } else {
        // Anything else is home
        fragment = new HomeFragment();
    }

    // Insert the fragment by replacing any existing fragment
    FragmentManager fragmentManager = getSupportFragmentManager();
    fragmentManager.beginTransaction()
            .replace(R.id.content, fragment)
            .commit();

    DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
    drawer.closeDrawer(GravityCompat.START);
    return true;
}
This code receives the selected menu id, and based on the id it shows the relavant fragment.

Step 20:
Save all the changes and run the application.


Find the project @ Git Hub.

If you have any problems or suggestions regarding this project, please comment below.
Previous
Next Post »

11 comments

Write comments
rajeshtk
AUTHOR
January 25, 2016 at 4:00 AM delete

How i can set values of nav_header_main.xml ( imageView,textView) by program ( like logged in username and details) , when i try to access those fields in main activity class , it shows null exception

Reply
avatar
rajeshtk
AUTHOR
January 25, 2016 at 10:58 AM delete

navHeaderView= navigationView.inflateHeaderView(R.layout.nav_header_main);
tvHeaderName= (TextView) navHeaderView.findViewById(R.id.tvHeaderName);
tvHeaderName.setText("Saly");

Reply
avatar
Gobinath
AUTHOR
January 27, 2016 at 10:29 AM delete

Hi jajeshtk,
Define android:id="@+id/txtTitle" for the first TextView of nav_header_main.xml

Then use this code after the onCreate method.
TextView txtTitle = (TextView) navigationView.getHeaderView(0).findViewById(R.id.txtTitle);
txtTitle.setText("Saly");

Reply
avatar
Gobinath
AUTHOR
January 27, 2016 at 10:31 AM delete

I have replied the answer to your second comment. You can apply the same logic for ImageView as well. If it is not working, please comment again :)

Reply
avatar
Soni Kumar
AUTHOR
January 29, 2016 at 12:10 PM delete

I want to change background color of only two navigation items .
Just like below image..

Reply
avatar
Soni Kumar
AUTHOR
January 29, 2016 at 12:27 PM delete

How to customize navigation drawer just like below image ..

Reply
avatar
Soni Kumar
AUTHOR
January 29, 2016 at 1:32 PM delete

How to change background color of only two navigation drawer items.

Reply
avatar
Rana Laiq Ahmed
AUTHOR
July 13, 2016 at 6:17 PM delete

I want to do that in my application that when I click on the home view in navigation drawer then "Home" should be displayed as you have shown above. But when I click in the Setting view then "Home" must be changed into "Settings". Will it be done a single fragment or different fragments?

Reply
avatar
Gobinath
AUTHOR
July 14, 2016 at 9:38 AM delete

Hi,
You need to have two Fragments. The above project has what you want. For your reference, check the project code (GitHub link is given at the bottom of the article) there I have created two fragments one for Home and another for Settings. If you click on Home, it will show the Home fragment. Similarly if you click on Settings, it will show the Settings fragment.
If you still have any issues, feel free to comment below.

Reply
avatar
Athini Bashe
AUTHOR
July 14, 2016 at 5:36 PM delete

I have been looking for a way to close the currently opened fragment. In most apps the menu icon of the nav drawer when clicked it would change to a back arrow icon "syncState" and when the back arrow icon clicked would close the fragment and take you back to the app's main activity not last fragment. is there a method to close any opened fragment by clicking on the floating bottom right icon? in your example

Reply
avatar
Athini Bashe
AUTHOR
July 14, 2016 at 7:23 PM delete

i found a way thanks

Reply
avatar

Contact Form

Name

Email *

Message *