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).
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;
}
}
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.
18 comments
Write commentsHow 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
ReplynavHeaderView= navigationView.inflateHeaderView(R.layout.nav_header_main);
ReplytvHeaderName= (TextView) navHeaderView.findViewById(R.id.tvHeaderName);
tvHeaderName.setText("Saly");
Hi jajeshtk,
ReplyDefine 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");
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 :)
ReplyI want to change background color of only two navigation items .
ReplyJust like below image..
How to customize navigation drawer just like below image ..
ReplyHow to change background color of only two navigation drawer items.
ReplyI 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?
ReplyHi,
ReplyYou 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.
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
Replyi found a way thanks
ReplyNice article.. For kotlin implementation please review https://www.android4dev.com/navigation-drawer-using-navigation-view-in-android/
ReplysetDrawerListener is depreciated, which one we can use instead in this project?
ReplyThanks for pointing it.
ReplyPlease check the addDrawerListener method. I will update the article soon.
changing navigation drawer icon colors in android https://www.youtube.com/watch?v=waem3_DNuss
Replynice tutorial. you can also read this article for implementing navigation drawer in kotlin: Implementing Navigation Drawer in Android App using Kotlin
ReplyHow can I add a Switch button on the Navigation Drawer (probably somewhere in the header) to change the Dark/light mode ? Like Telegram's app, for example
Reply🙏
How can I add a Switch on the Navigation Drawer (or eventually somewhere in the header) to change the Dark/light mode ? Like Telegram's app, for example
Reply🙏
EmoticonEmoticon