The navigation drawer is a UI panel that shows your app's main navigation menu. It is hidden when not in use, but appears when the user swipes a finger from the left edge of the screen or, when at the top level of the app, the user touches the drawer icon in the app bar.
This page shows you how to implement a navigation drawer using the
DrawerLayout APIs available in the
Support Library.
Navigation Drawer Design
Before you decide to use a navigation drawer in your app, you should understand the use cases and design principles defined in the Navigation Drawer design guide.
Figure 1. A navigation drawer
Add dependencies
This page uses APIs from on the Android Support Library, so you need
to add the following dependencies to your apps module's build.gradle file:
dependencies {
implementation 'com.android.support:appcompat-v7:27.1.1'
implementation 'com.android.support:design:27.1.1'
}
Add a drawer to your layout
To add a navigation drawer, declare your layout with a
DrawerLayout as the root view.
Inside the DrawerLayout, add
a layout for the main content for the UI (your primary layout when the drawer
is hidden) and another view that contains the contents of the navigation
drawer.
For example, the following layout uses a
DrawerLayout with two child views: a
FrameLayout to contain the main content (which could,
for example, by populated by a Fragment at
runtime), and a NavigationView for the
contents of the navigation drawer.
<?xml version="1.0" encoding="utf-8"?>
<!-- Use DrawerLayout as root container for activity -->
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<!-- Layout to contain contents of main body of screen (drawer will slide over this) -->
<FrameLayout
android:id="@+id/content_frame"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<!-- Container for contents of drawer - use NavigationView to make configuration easier -->
<android.support.design.widget.NavigationView
android:id="@+id/nav_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:fitsSystemWindows="true" />
</android.support.v4.widget.DrawerLayout>
This example demonstrates some important layout characteristics:
-
The
FrameLayoutis set to match the parent view's width and height, because it represents the entire UI when the navigation drawer is closed. -
The
NavigationView(the drawer) must specify its horizontal gravity with theandroid:layout_gravityattribute. To support right-to-left (RTL) languages, specify the value with"start"instead of"left"(so the drawer appears on the right when the layout is RTL). - The
NavigationViewsetsandroid:fitsSystemWindowsto"true"to ensure the contents of the drawer don’t overlay the status bar and other system windows. TheDrawerLayoutalso usesfitsSystemWindowsas a sign that it needs to inset its children (such as the main content view), but still draw the status bar background in that space as per the material design specs (which defaults to your theme’scolorPrimaryDark).
Declare the menu items for the nav drawer
To configure the menu items listed in the drawer, specify a menu resource
with the app:menu attribute, as shown in the example code below:
<android.support.design.widget.NavigationView
android:id="@+id/nav_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:fitsSystemWindows="true"
app:menu="@menu/drawer_view" />
Create the menu resource
with the corresponding file name. For example, at res/menu/drawer_view.xml:
<?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_camera"
android:icon="@drawable/ic_menu_camera"
android:title="@string/import" />
<item
android:id="@+id/nav_gallery"
android:icon="@drawable/ic_menu_gallery"
android:title="@string/gallery" />
<item
android:id="@+id/nav_slideshow"
android:icon="@drawable/ic_menu_slideshow"
android:title="@string/slideshow" />
<item
android:id="@+id/nav_manage"
android:icon="@drawable/ic_menu_manage"
android:title="@string/tools" />
</group>
</menu>
You can make a group of items single-selectable by applying
android:checkableBehavior="single" to a group. This allows you
to show which list item is currently selected.
To learn more about creating a menu XML file, see the Menu resource documentation.
Add a header to the nav drawer
Optionally, you can add a header at the top of the drawer, by specifying a layout with the
app:headerLayout attribute as shown here:
<android.support.design.widget.NavigationView
android:id="@+id/nav_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:fitsSystemWindows="true"
app:menu="@menu/drawer_view"
app:headerLayout="@layout/nav_header" />
The following is an example header layout that provides a title:
<?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="192dp"
android:background="?attr/colorPrimaryDark"
android:padding="16dp"
android:theme="@style/ThemeOverlay.AppCompat.Dark"
android:orientation="vertical"
android:gravity="bottom">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="My header title"
android:textAppearance="@style/TextAppearance.AppCompat.Body1"/>
</LinearLayout>
For design recommendations for the navigation drawer header sizing, spacing, and typography, see Patterns - Navigation drawer.
Handle navigation click events
To receive callbacks when the user taps a list item in the drawer, implement the
OnNavigationItemSelectedListener interface and attach it to your
NavigationView by calling
setNavigationItemSelectedListener().
For example:
public class MainActivity extends AppCompatActivity {
private DrawerLayout mDrawerLayout;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mDrawerLayout = findViewById(R.id.drawer_layout);
NavigationView navigationView = findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(
new NavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(MenuItem menuItem) {
// set item as selected to persist highlight
menuItem.setChecked(true);
// close drawer when item is tapped
mDrawerLayout.closeDrawers();
// Add code here to update the UI based on the item selected
// For example, swap UI fragments here
return true;
}
});
}
}
When an item is tapped, this code sets the selected item as checked,
changing the list item's style to be highlighted because the list
items are part of a checkable group (as shown above in the menu file).
It also closes the drawer by calling
closeDrawers().
If your app switches out content based on which navigation menu item the user selects, you should consider using fragments in the main content area. Swapping fragments when you navigate from the navigation drawer allows for a seamless drawer animation, because the same base layout stays in place. To learn how to build your layout with fragments, see the Fragments documentation.
Add the nav drawer button to the app bar
At this point, you already have a working navigation drawer—the
DrawerLayout provides built-in support for users to
open and close the navigation drawer with a swipe on the side of the screen.
But if your UI design includes an app bar,
you should also allow users to open and close the drawer by touching the drawer icon on the
top left of the app bar (as shown in figure 2). That's what you'll do in this section.
Figure 2. An app bar with the nav drawer button on the left
Add the toolbar to your layout
To make your UI meet the material design guidelines, the navigation drawer should appear
in front of the app bar (as shown in figure 1), not below it.
To make that happen, you need to use Toolbar
as your app bar, instead of using a theme with a built-in app bar. You can add
Toolbar to your layout as follows:
<android.support.v4.widget.DrawerLayout ...>
<FrameLayout
android:id="@+id/content_frame"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:theme="@style/ThemeOverlay.AppCompat.ActionBar" />
</FrameLayout>
...
</android.support.v4.widget.DrawerLayout>
Then open your manifest file and set the app theme to one without
the action bar, such as Theme.AppCompat.Light.NoActionBar:
<manifest ...>
<application
...
android:theme="@style/Theme.AppCompat.Light.NoActionBar" >
...
</manifest>
If you want to override some styles in this theme, see Styles and Themes.
Set the toolbar as the action bar
Now the toolbar appears in the layout but it's not functioning as the app bar.
To apply the toolbar as the app bar, first make sure your activity extends from
AppCompatActivity. Then
call setSupportActionBar() and pass the Toolbar object
from your layout:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
...
}
}
Add the nav drawer button
Now add the button that opens the navigation drawer. You first need to add the menu button's icon to your project. You can download a material menu icon from the Material Design Icons page, or import the icon from Android Studio:
- In the Project window, right-click the res folder and select New > Vector Asset.
- Select Material icon as the asset type and then click the Icon button to open the Select Icon window.
- Search for "menu" and select the menu icon (the icon is 3 horizontal lines).
- Click OK, and then rename the file to "ic_menu" and click Next to import it.
Enable the app bar's "home" button by calling setDisplayHomeAsUpEnabled(true), and then change it to use the menu icon by calling setHomeAsUpIndicator(int), as shown here:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
ActionBar actionbar = getSupportActionBar();
actionbar.setDisplayHomeAsUpEnabled(true);
actionbar.setHomeAsUpIndicator(R.drawable.ic_menu);
...
}
}
Open the drawer when the button is tapped
To open the drawer when the user taps on the nav drawer button, override
onOptionsItemSelected()
to hook into the options menu framework and listen for when the user taps
the item with the ID android.R.id.home. Then
call openDrawer() to open the nav drawer:
public class MainActivity extends AppCompatActivity {
private DrawerLayout mDrawerLayout;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mDrawerLayout = findViewById(R.id.drawer_layout);
...
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
mDrawerLayout.openDrawer(GravityCompat.START);
return true;
}
return super.onOptionsItemSelected(item);
}
}
To learn more about handling options menu taps, see the Menus guide.
Notice that the code above passes
GravityCompat.START as
the open drawer animation gravity to openDrawer(). This
ensures your nav drawer open
animation behaves properly for both right-to-left and left-to-right layouts.
Listen for open/close events and other state changes
If your app needs to respond when the navigation drawer opens, closes, or simply changes
its state and position—which might be useful if you need to adjust other parts of your UI
based on the drawer's exact position—you should implement callback methods in the DrawerLayout.DrawerListener interface and pass it to addDrawerListener(). For example:
public class MainActivity extends AppCompatActivity {
private DrawerLayout mDrawerLayout;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mDrawerLayout = findViewById(R.id.drawer_layout);
...
mDrawerLayout.addDrawerListener(
new DrawerLayout.DrawerListener() {
@Override
public void onDrawerSlide(View drawerView, float slideOffset) {
// Respond when the drawer's position changes
}
@Override
public void onDrawerOpened(View drawerView) {
// Respond when the drawer is opened
}
@Override
public void onDrawerClosed(View drawerView) {
// Respond when the drawer is closed
}
@Override
public void onDrawerStateChanged(int newState) {
// Respond when the drawer motion state changes
}
}
);
}
...
}


