Navigation Patterns

Stack Based Navigation

Introduction

The core of navigation flows in Android apps centers around the Activity and the Intent. In this guide, we are going to review tasks, navigation, and how to manipulate these when navigating between activities.

This is typically used in cases where we need to exert more fine-tuned control over the behavior of the task stack which determines the “history” of our application.

Note: To skip to changing the behavior of the task stack, jump right to the [[Usage|Navigation-and-Task-Stacks#usage]] section of this document.

Conceptual Overview

While the concept of using intents to launch activities should already be familiar to you, let’s take a second to explore how launching new activities works and how this navigation is managed.

As we navigate around our app (or even between apps), Android is maintaining a task stack which tracks each step in the user’s history. A task is a collection of activities that users interact with when performing a certain job. The activities are arranged in a stack (the “back stack”), in the order in which each activity is opened. By default, your activities in your app are organized as part of the same task affinity group.

Understanding the Task Stack

When an application is launched from the Home Screen, the application comes to the foreground and the “stack” for that application becomes active. If no task stack exists for this application (first launch recently), then a new task is created and the “main” activity of the app becomes the first (root) item in the stack.

Each time an activity is launched in your app, that activity is pushed onto the top of the stack and becomes active. The previous activity remains in the stack but it is stopped. However, despite being stopped the system retains the state of the Activity UI automatically.

Task Stack

If the user hits “back”, the current activity is popped from the top of the stack (and destroyed) and the previous activity resumes with the previous UI state restored. If the user continues to press Back, then each activity in the stack is popped off to reveal the previous one, until the user returns to whichever task was happening before this task stack began.

Task Stacks Everywhere

A “task” is a collection of activities stemming from a “root” application. This group is cohesive and when the user hits the home screen, the entire “task” is moved to the background until the stack is re-activated. While in the background, all the activities in the task are stopped, but the back stack for the task remains intact.

MultiTasking

If the user were to open another separate application now, that app would have an entirely separate task stack that would come to the foreground. This means that multiple discrete stacks frequently are stored by the system. There might be several task stacks in the background and when the user re-enters the related application, that stack will reappear in the foreground with states restored.

Multiple Activity Instances

This process of multiple task stacks is just the beginning. The real point of understanding comes from exploring what happens when we launch the same activity multiple times. Because the activities in the back stack are never rearranged, every time an activity is started via an intent, a brand new instance of that activity is created and pushed onto the stack.

This means that if you have an activity (say the timeline for twitter), and you launch the timeline activity multiple times using different intents, then multiple instances of that activity will be tracked in the stack.

Multiple Activity

This gets even more complex when you consider you might launch the same Activity from multiple different task stacks. For example, think about how many apps might launch the browser and how many instances of a browser you might have across all task stacks.

By default, if the user navigates backward using the Back button, each instance of the activity is revealed in the order in which they were opened (each with their own UI state).

See Tasks and Back Stack official guide for the source of the above content and additional details.

Affinity Groups

Activities within your application all belong to the same affinity group unless you define one differently using the taskAffinity XML property:

<activity android:name=".activities.MyActivity"
android:taskAffinity="com.codepath.myapp">

You can group activities together in this way to dismiss them all at once:

ActivityCompat.FinishAffinity(this); // equivalent to finish(true); on Android devices API > 4

When using FinishAffinity(), you may notice that the activity can still show up in the Most Recents screen. You can use the android:autoRemoveFromRecents flag to be true to remove it, which is normally set to false by default. You can also use finishAndRemoveTask() to accomplish the same effect.

<activity android:name=".MyActivity"
android:autoRemoveFromRecents="true"
android:taskAffinity="com.codepath.myapp"/>

Usage

The behavior described above works automatically and without any special configuration from the developer. The default behavior is to just place all activities started in succession in the same task and in a “last in, first out” stack.

However, there are cases where this behavior may not suit your needs. In the event that you want to tune or tweak this behavior, we need to understand how to change the behavior of our task stack. For example, we might want to:

  • Have an activity in your application to begin a new task when it is started
  • Want to bring forward an existing instance of an activity (rather than create a new one)
  • Want to clear the history of the back stack at a particular point

In order to change this behavior, there are two approaches available:

  • Activity Properties - Setting properties on the activity within the manifest that changes the task stack behavior.
  • Intent Flags - Adding flags to an intent in order to change the task stack behavior for that launch.

If you always want an Activity to show a particular kind of behaviour then you will set the property in the <activity> element corresponding to that Activity in the manifest.

If you only want to exclude it from recent tasks under certain one-off conditions then you set the flag in the Intent and not the manifest.

Configuring Activity Properties

The first approach to modifying the task stack is to set properties on the element within the AndroidManifest.xml.

Launch Modes

To tweak the behavior of the Activity in the manifest, we want to set the launchMode attribute. This looks like:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.todoapp"
    … >
    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        ... >
        <activity
            android:name="com.example.todoapp.TodoActivity"
            android:label="@string/app_name" 
            android:launchMode="singleTop">
        </activity>
    </application>
</manifest>

Notice there we have specified the launchMode as “singleTop”. There are four different “launch modes” to choose from that alter the task stack behaviors for that activity:

  • standard - The default behavior. Creates a new instance of the activity in the task.
  • singleTop - Reuse an activity instance if already at the top of the stack; otherwise create new instance.
  • singleTask - Reuse an activity instance if exists in an existing stack; otherwise create in a new task stack.
  • singleInstance - Same as singleTask but no other activities are ever inserted into the created task stack.

See the official guide for stacks for a more detailed explanation. This table may help clarify the different launch modes:

Mode Default Instantiation New Task on Launch Allow other activities within Task
standard Yes Everytime an intent is created, a new instance is created. Also instances can be member of multiple tasks and more than one instance in a Task. No. Open in the same Task that originated the intent Yes
singleTop No Exactly like standard but if the activity is at the top of the Task stack then it uses the existing instance. No. Open in the same Task that originated the intent Yes
singleTask No Single instance Yes. Always a Root Task. Yes
singleInstance No Single instance Yes. Always a Root Task. Never. Always the only activity in the task

It might be useful to understand when various modes might be appropriate in an application. The following provides examples:

  • singleTask - There is only one BrowserActivity at a time and it doesn’t become part of tasks that send it intents to open web pages. While it might return to whatever most recently launched it when you hit back it is actually fixed at the bottom of its own task activity stack.
  • singleTop - While there can be multiple instances of the BrowserBookmarksPage if there is already one at the top of the task’s activity stack it will be reused. This way you only have to hit back once to return to the browser if the bookmarks activity is started multiple times.
  • singleInstance - Only one AlarmAlert activity at a time and it is always its own task. Anything it might launch (if anything) becomes a part of a separate task stack.

Check out the understanding launch modes guide for more detailed examples. Also check out this blog post for another explanation.

Configuring No History

There are additional properties as well that can be set on an activity. For example, if an activity should not be added to the task stack at all, simply set the noHistory flag within the manifest:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.todoapp"
    … >
    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        ... >
        <activity
            android:name="com.example.todoapp.TodoActivity"
            android:label="@string/app_name" 
            android:noHistory="true">
        </activity>
    </application>
</manifest>

Once this is set, that activity will never be a part of the stack even when launched. You might also want to check out the taskAffinity property as well as the allowTaskReparenting properties for more fine tuned control over the activity’s behavior in the task stack.

Configuring Intent Flags

The other approach to modifying the task stack is to set flags within an intent when starting an Activity.

You can alter the task stack behavior by appending various flags when launching an intent. For example, to clear the task stack when starting a new activity, we can do:

Intent i = new Intent(this, typeof(SecondActivity);
// Add flags into the intent to alter behavior
i.intent.SetFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
IntentCompat.FLAG_ACTIVITY_CLEAR_TASK);
// Execute as normal
StartActivity(i);

The above can be very useful for login activities. The flags launch a new activity such that when the user presses “back”, the previous activity would not show up. The following other flags are available to be set on the intent:

  • FLAG_ACTIVITY_CLEAR_TASK - Clear any existing tasks on this stack before starting the activity.
  • FLAG_ACTIVITY_NEW_TASK - Start the activity in a new task or reuse an existing task tied to that activity.
  • FLAG_ACTIVITY_SINGLE_TOP - If the activity being started is the same as the current activity, then reuses the existing instance which receives a call to onNewIntent()
  • FLAG_ACTIVITY_CLEAR_TOP - If the activity being started is already running in the current task, delivers us back to the existing instance and clears the stack.

There are almost a dozen other flags you can set as well, for example FLAG_ACTIVITY_BROUGHT_TO_FRONT, FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS, and FLAG_ACTIVITY_MULTIPLE_TASK. For a more comprehensive list, check out this article.

See the official guide for stacks for a more detailed explanation.

Providing Proper Navigation

Check out the excellent Providing Back Navigation and Providing Up Navigation guides for details on how to ensure you properly provide both of these navigation directions.

Tabbed Navigation with ViewPager and TabLayout

You use a ViewPager together with the TabLayout to create tabbed navigation.

To only support swipe navigation without tabs you can use the ViewPager on its own.

Add the Support Library V4

The ViewPager is found in the Android Support V4

Add the Support Design Library

To get the TabLayout, you need to add the Support Design Library

Adding ViewPager and TabLayout

You will need to add the ViewPage and TabLayout to layout resource file :

Resources/layout/Main.axml

<?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:orientation="vertical">
    
    <android.support.design.widget.TabLayout
        android:id="@+id/tabLayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
    
    <android.support.v4.view.ViewPager
        android:id="@+id/viewPager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:padding="16dp" />
</LinearLayout>

Adding an Adapter for the ViewPager

The ViewPager works the same as the ListView, it requires an adapter to supply the fragments it will use to display.

PageAdapter.cs

class PagesAdapter : FragmentPagerAdapter {
	List<Fragment> fragmentList;
	List<ICharSequence> titles;
	
	public PagesAdapter(Android.Support.V4.App.FragmentManager fm, List<Fragment> fragmentList, List<ICharSequence> titles) : base(fm) {
		this.fragmentList = fragmentList;
		this.titles = titles;
	}
	
	public override int Count
	{
		get {
		    return fragmentList.Count;
		}
	}
	
	public override Fragment GetItem(int position)
	{
		return fragmentList[position];
	}
	
	public override Java.Lang.ICharSequence GetPageTitleFormatted(int position)
	{
		return titles[position];
	}
}

The PageAdapter inherits from the FragmentPageAdapter and implements the required methods.

Create the Fragments Classes to be Displayed

The ViewPager will need fragments to display when you swipe

MoviesFragment.cs

public class MoviesFragment : Fragment
{
	public override void OnCreate(Bundle savedInstanceState)
	{
		base.OnCreate(savedInstanceState);
	}

	public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
	{
		return inflater.Inflate(Resource.Layout.activity_movies, container, false);
	}
}

and the backing xml file for it :

Resources/layout/activity_movies.axml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:text="Movies"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
</LinearLayout>

FavoriteMoviesFragment.cs

public class FavoriteMoviesFragment : Fragment
{
	public override void OnCreate(Bundle savedInstanceState)
	{
		base.OnCreate(savedInstanceState);
	}

	public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
	{
		return inflater.Inflate(Resource.Layout.activity_favorite_movies, container, false);
	}
}

and the backing xml layout resource file

Resources/layout/activity_favorite_movies.axml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:text="Favorite Movies"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</LinearLayout>

PopularMoviesFragment.cs

public class PopularMoviesFragment : Fragment
{
	public override void OnCreate(Bundle savedInstanceState)
	{
		base.OnCreate(savedInstanceState);
	}

	public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
	{
		return inflater.Inflate(Resource.Layout.activity_popular_movies, container, false);
	}
}

and its backing xml resource file

Resources/layout/activity_popular_movies.axml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:padding="16dp"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:text="Popular Movies"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

</LinearLayout>

Bind the ViewPager and Setup TabLayout

We can now find the Viewpager and TabLayout and create the adapter and attach it to the ViewPager.

MainActivity.cs

[Activity(Label = "SwipeViewDemo", MainLauncher = true, Icon = "@mipmap/icon", Theme = "@style/AppTheme")]

	public class MainActivity : AppCompatActivity
	{
		ViewPager viewPager;
		List<Fragment> fragmentList = new List<Fragment>();
		List<ICharSequence> titles = new List<ICharSequence>();
		PagesAdapter adapter;
		TabLayout tabLayout;
	
	protected override void OnCreate(Bundle savedInstanceState)
	{
		base.OnCreate(savedInstanceState);
		// Set our view from the "main" layout resource
		SetContentView(Resource.Layout.activity_main);
		viewPager = FindViewById<ViewPager>(Resource.Id.viewPager);
		tabLayout = FindViewById<TabLayout>(Resource.Id.tabLayout);
		tabLayout.TabMode = TabLayout.ModeFixed;
		tabLayout.TabGravity = TabLayout.GravityFill;
		fragmentList.Add(new MoviesFragment());
		titles.Add(new Java.Lang.String("Movies"));
		fragmentList.Add(new PopularMoviesFragment());
		titles.Add(new Java.Lang.String("Popular"));
		fragmentList.Add(new FavoriteMoviesFragment());
		titles.Add(new Java.Lang.String("Favorite"));
		adapter = new PagesAdapter(SupportFragmentManager, fragmentList, titles);
		viewPager.Adapter = adapter;
		tabLayout.SetupWithViewPager(viewPager);
	}
}

With the release of Android 5.0 Lollipop, the new material design style navigation drawer spans the full height of the screen and is displayed over the ActionBar and overlaps the translucent StatusBar. Read the material design style navigation drawer document for specs on styling your navigation drawer.

Usage

This guide explains how to setup a basic material design style drawer filled with navigation items that switch different fragments into the content area. In this way, you can define multiple fragments, and then define the list of options which will display in the drawers items list. Each item when clicked will switch the relevant fragment into the activity’s container view.

Setup

Make sure to setup the Google Design Support Library before using Google’s new NavigationView, announced as part of the Android M release. The NavigationView should be backwards compatible with all versions down to Android 2.1.

Add the Design Support Library from Nuget.

Setup Drawer Resources

Create a menu/drawer_view.xml file:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:android="http://schemas.android.com/apk/res/android">

    <group android:checkableBehavior="single">
        <item
            android:id="@+id/action_popular"
            android:title="Popular" />
        <item
            android:id="@+id/action_showing"
            android:title="Showing"/>
        <item
            android:id="@+id/action_favorites"
            android:title="Favorites" />
    </group>
</menu>

Note that you can set one of these elements to be default selected by using android:checked="true".

You can also create subheaders too and group elements together:

 <item android:title="Sub items">
        <menu>
            <group android:checkableBehavior="single">
                <item
                    android:icon="@drawable/ic_dashboard"
                    android:title="Sub item 1" />
                <item
                    android:icon="@drawable/ic_forum"
                    android:title="Sub item 2" />
            </group>
        </menu>
    </item>

Define Fragments

Next, you need to define your fragments that will be displayed within the drawer. These can be any support fragments you define within your application. Make sure that all the fragments extend from android.support.v4.app.Fragment.

Setup Toolbar

In order to slide our navigation drawer over the ActionBar, we need to use the new [[Toolbar|Using-the-App-ToolBar]] widget as defined in the AppCompat v21 library. The Toolbar can be embedded into your view hierarchy which makes sure that the drawer slides over the ActionBar.

Create a new layout file res/layout/toolbar.xml with the following code:

<android.support.v7.widget.Toolbar
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/toolbar"
    android:layout_height="wrap_content"
    android:layout_width="match_parent"
    android:fitsSystemWindows="true"
    android:minHeight="?attr/actionBarSize"
    app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
    android:background="?attr/colorPrimaryDark">
</android.support.v7.widget.Toolbar>

Note that when the android:fitsSystemWindows attribute is set to true for a view, the view would be laid out as if the StatusBar and the ActionBar were present i.e. the UI on top gets padding enough to not be obscured by the navigation bar. Without this attribute, there is not enough padding factored into consideration for the ToolBar:

We want our main content view to have the navigation bar and hence android:fitsSystemWindows is set to true for the Toolbar.

To use the Toolbar as an ActionBar, you need to disable the default ActionBar. This can be done by setting the app theme in styles.xml file.

<resources>
    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <item name="colorPrimary">#673AB7</item>
        <item name="colorPrimaryDark">#512DA8</item>
        <item name="colorAccent">#FF4081</item>
    </style>
</resources>

Also note that normally you should decide on your color scheme by going to Material Palette and choosing a primary and dark primary color. For this example, we will pick purple-based colors as shown in the screenshot.

Note

If you forget to disable the ActionBar in styles.xml, you are likely to see an error message that reads This Activity already has an action bar supplied by the window decor. Do not request Window.FEATURE_ACTION_BAR and set windowActionBar to false in your theme to use a Toolbar instead. If you see this message, you need to make sure to follow the previous steps.

Setup Drawer in Activity

Next, let’s setup a basic navigation drawer based on the following layout file which has the entire drawer setup in res/layout/activity_main.xml. Note that the Toolbar is added as the first child of the main content view by adding the include tag.

Main.axml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_height="match_parent">

    <include
        layout="@layout/toolbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <android.support.v4.widget.DrawerLayout
        android:id="@+id/drawer"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <FrameLayout
            android:id="@+id/container"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>

        <android.support.design.widget.NavigationView
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:id="@+id/navigationView"
                android:layout_gravity="start"
                app:menu="@menu/drawer_menu" />

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

Now, let’s setup the drawer in our activity. We can also setup the menu icon too.

Note: Make sure you implement the correct OnPostCreate(Bundle savedInstanceState) method. There are 2 signatures and only OnPostCreate(Bundle state) shows the hamburger icon.

using Android.App;
using Android.Widget;
using Android.OS;
using Android.Support.V7.App;
using Android.Support.V4.Widget;
using Android.Support.Design.Widget;
using Android.Support.V7.Widget;
using Android.Support.V7.Widget;
using Android.Support.V4.View;


namespace NavigationDrawerDemoTest
{
	[Activity(Label = "Rotten Tomatoes", MainLauncher = true, Icon = "@mipmap/icon", Theme = "@style/NoActionBar")]
	public class MainActivity : AppCompatActivity
	{
		DrawerLayout drawer;
		NavigationView navigationView;
		ActionBarDrawerToggle toggle;
		Android.Support.V7.Widget.Toolbar toolbar;

		protected override void OnCreate(Bundle savedInstanceState)
		{
			base.OnCreate(savedInstanceState);

			// Set our view from the "main" layout resource
			SetContentView(Resource.Layout.Main);

			drawer = FindViewById<DrawerLayout>(Resource.Id.drawer);
			navigationView = FindViewById<NavigationView>(Resource.Id.navigationView);
			toolbar = FindViewById<Android.Support.V7.Widget.Toolbar>(Resource.Id.toolbar);

			SetSupportActionBar(toolbar);

			toggle = new ActionBarDrawerToggle(this, drawer, toolbar, Resource.String.drawer_open, Resource.String.drawer_close);
			SupportActionBar.SetHomeButtonEnabled(true);
			SupportActionBar.SetDisplayShowTitleEnabled(true);

			drawer.AddDrawerListener(toggle);
			toggle.SyncState();

			navigationView.NavigationItemSelected += (object sender, NavigationView.NavigationItemSelectedEventArgs e) => {
				switch (e.MenuItem.ItemId) {
					case Resource.Id.action_showing:
						Toast.MakeText(this, "Showing", ToastLength.Short).Show();
						//Code to change the fragment here.
						//FragmentManager
						//	.BeginTransaction()
						//	.Replace(Resource.Id.container, new PopularMoviesFragment())
						//	.Commit();

						drawer.CloseDrawer(GravityCompat.Start);
						break;
					case Resource.Id.action_popular:
						Toast.MakeText(this, "Popular", ToastLength.Short).Show();
						break;
					case Resource.Id.action_favorites:
						Toast.MakeText(this, "showing", ToastLength.Short).Show();
						break;
				}
			};

		}

		public override bool OnOptionsItemSelected(Android.Views.IMenuItem item)
		{
			if (toggle.OnOptionsItemSelected(item)) {
				return true;
			}

			switch (item.ItemId) {
				case Android.Resource.Id.Home:
					drawer.OpenDrawer(GravityCompat.Start);	
					break;
			}

			return base.OnOptionsItemSelected(item);
		}

		protected override void OnPostCreate(Bundle savedInstanceState)
		{
			base.OnPostCreate(savedInstanceState);
			toggle.SyncState();
		}

		public override void OnConfigurationChanged(Android.Content.Res.Configuration newConfig)
		{
			base.OnConfigurationChanged(newConfig);
			toggle.OnConfigurationChanged(newConfig);
		}
	}
}
navigationView.NavigationItemSelected += (object sender, NavigationView.NavigationItemSelectedEventArgs e) => {
	switch (e.MenuItem.ItemId) {
		case Resource.Id.action_showing:
			FragmentManager
				.BeginTransaction()
				.Replace(Resource.Id.container, new MoviesShowingFragment())
				.Commit();
				drawer.CloseDrawer(GravityCompat.Start);
				e.MenuItem.setChecked(true);
	          //Set action bar title
   		       SetTitle(MenuItem.Title);
				break;
		case Resource.Id.action_popular:
				FragmentManager
				.BeginTransaction()
				.Replace(Resource.Id.container, new PopularMoviesFragment())
				.Commit();
				drawer.CloseDrawer(GravityCompat.Start);
				e.MenuItem.setChecked(true);
	          //Set action bar title
   		       SetTitle(MenuItem.Title);
				break;
		case Resource.Id.action_favorites:
				FragmentManager
				.BeginTransaction()
				.Replace(Resource.Id.container, new FavoriteMoviesFragment())
				.Commit();
				drawer.CloseDrawer(GravityCompat.Start);
				e.MenuItem.setChecked(true);
	          //Set action bar title
   		       SetTitle(MenuItem.Title);
				break;
	}
};

One thing to note is that the ActionBarDrawerToggle renders a custom DrawerArrowDrawable for you for the hamburger icon.

Making Status Bar Translucent

To have the status bar translucent and have our drawer slide over it, we need to set android:windowTranslucentStatus to true. Because this style is not available for pre Kitkat devices, we’ll add res/values-v19/styles.xml file for API version 19 and onwards. Note: If you modify your res/values/styles.xml directly with this android:windowTranslucentStatus line, you are likely to need to build only for SDK versions 19 or higher, which will obviously limit you from supporting many older devices.

In res/values-v19/styles.xml we can add the following:

<resources>
  <!-- Base application theme. -->
  <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
    <!-- Customize your theme here. -->
    <item name="android:windowTranslucentStatus">true</item>
  </style>
</resources>

Now if you run your app, you should see the navigation drawer and be able to select between your fragments.

Adding custom views to navigation drawer

One improvement made to the design support library 23.1.0 is the addition of support for custom views for the navigation drawer items. For instance, we can create a custom switch like the navigation drawer from Google Play Movies for one of the rows:

The approach is the same as adding [[ActionView items|Extended-ActionBar-Guide#adding-actionview-items]] to the ActionBar. We simply need to define a separate layout such as the following snippet. We will call this file action_view_switch.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal" android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.v7.widget.SwitchCompat
        android:layout_width="fill_parent"
        android:layout_height="match_parent"
        android:text="Switch"/>
</LinearLayout>

We then reference this layout using the app:actionLayout attribute. A title must be provided but can also be set to blank:

<menu xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:android="http://schemas.android.com/apk/res/android">
  <item android:id="@+id/nav_switch"
        app:actionLayout="@layout/action_view_switch"
        android:title="Downloaded only" />
  </item>
</menu>

You can attach events directly in XML so long as your Activity will implement the method. To add an event handling to the toggle switch programmatically through Java, you will need to first get the menu instance and get access to the corresponding ActionView:

Menu menu = navigationView.getMenu();
MenuItem menuItem = menu.findItem(R.id.nav_switch);
View actionView = MenuItemCompat.getActionView(menuItem);
actionView.setOnClickListener(new View.OnClickListener() {
  @Override
  public void onClick(View v) {
                
  }
});

Custom widgets using app:actionViewClass can also be used too for menu items as well now too. For more details about how Action Views, see adding the [[SearchView to ActionBar|Extended-ActionBar-Guide#adding-searchview-to-actionbar]] guide.

Persistent Navigation Drawer

In certain situations, especially on tablets, the navigation drawer should be a permanent fixture on the activity acting as a sidebar:

Persistent

To achieve this effect, review the following links which describe one approach:

Third-party libraries may also make this easier to achieve.

Third-Party Libraries

There are a few third-party libraries that are still relevant as possible alternatives to using the DrawerLayout directly which provide certain material design elements automatically:

Often these are unnecessary but check them out to see the functionality they provide.

Limitations

The current version of the design support library does come with its limitations. The main issue is with the system that highlights the current item in the navigation menu. The itemBackground attribute for the NavigationView does not handle the checked state of the item correctly: somehow either all items are highlighted or none of them are. This makes this attribute basically unusable for most apps.

Alternative to Fragments

Although many navigation drawer examples show how fragments can be used with the navigation drawer, you can also use a RelativeLayout/LinearLayout if you wish to use the drawer as an overlay to your currently displayed Activity.

Instead of <FrameLayout> you can substitute that for a <LinearLayout>

<android.support.v4.widget.DrawerLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/drawer_layout">

        <LinearLayout
                android:id="@+id/content_frame"
                android:orientation="horizontal"
                android:layout_width="match_parent"
                android:layout_height="match_parent"/>

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

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

Instead of this:

// Insert the fragment by replacing any existing fragment
getFragmentManager().beginTransaction()
       .replace(R.id.content_frame, fragment)
       .commit();

You can instead use the LinearLayout container to inflate the Activity directly:

LayoutInflater inflater = getLayoutInflater();
LinearLayout container = (LinearLayout) findViewById(R.id.content_frame);
inflater.inflate(R.layout.activity_main, container);

References