Material 3 Navigation Drawers in Android with Developer Documentation

Material 3 Navigation Drawers

Overview

Navigation drawers provide access to app destinations.

Material 3 Navigation Drawers, using NavigationView, come in Standard (persistent) and Modal (temporary with scrim) variants, but are deprecated in favor of expanded navigation rails in the Material 3 Expressive update. This guide covers implementation, accessibility, and theming for legacy use.

Using Navigation Drawers

Accessibility

  • Set android:contentDescription on menu items and header images for TalkBack
  • Ensure open/close controls meet 48dp touch targets
  • Support keyboard navigation with ESC key to close drawers
  • Menu items are auto-readable by accessibility services

Behavior and Configuration

  • Configure menus via XML resources, headers via layouts
  • Handle item selection with setNavigationItemSelectedListener
  • Use DrawerLayout for Modal drawer open/close with predictive back support
      
val drawerLayout = findViewById<DrawerLayout>(R.id.drawer_layout)
val navigationView = findViewById<NavigationView>(R.id.navigation_view)
navigationView.setNavigationItemSelectedListener { menuItem ->
    menuItem.isChecked = true
    drawerLayout.close()
    true
}
      
    

Navigation Drawer Variants

  1. Standard Navigation Drawer: Persistent, coexists with content, for larger screens
  2. Modal Navigation Drawer: Temporary, blocks content with scrim, for mobile devices

Standard Navigation Drawer

  • Permanently visible, ideal for tablets/desktops
  • Uses NavigationView within ConstraintLayout

Standard Navigation Drawer Anatomy

Component Description Active State Inactive State
Container Permanent, 280dp max width, 0dp elevation Holds active item Holds inactive items
Headline Optional header text Visible if set Visible if set
Label Text Menu item titles Highlighted with colorOnSecondaryContainer Faded with colorOnSurfaceVariant
Icon Menu item icons, 24dp Highlighted with colorOnSecondaryContainer Faded with colorOnSurfaceVariant
Active Indicator Highlights active item, rounded shape Visible, colorSecondaryContainer Not visible
Badge Label Text Optional counts/status indicators Visible if set Visible if set

Example

      
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <com.google.android.material.navigation.NavigationView
        android:id="@+id/navigation_view"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        app:headerLayout="@layout/header_navigation_drawer"
        app:menu="@menu/navigation_drawer"
        app:layout_constraintStart_toStartOf="parent"/>
    <!-- Screen content -->
</androidx.constraintlayout.widget.ConstraintLayout>
      
    
      
<!-- res/menu/navigation_drawer.xml -->
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:id="@+id/main_item"
        android:title="@string/mail_subheader">
        <menu>
            <item
                android:id="@+id/inbox_item"
                android:icon="@drawable/ic_inbox_24"
                android:title="@string/inbox"
                android:checkable="true"/>
            <item
                android:id="@+id/outbox_item"
                android:icon="@drawable/ic_outbox_24"
                android:title="@string/outbox"
                android:checkable="true"/>
        </menu>
    </item>
</menu>
      
    
      
val navigationView = findViewById<NavigationView>(R.id.navigation_view)
navigationView.setNavigationItemSelectedListener { menuItem ->
    menuItem.isChecked = true
    true
}
      
    

Modal Navigation Drawer

  • Temporary, blocks content with a scrim
  • Ideal for mobile devices
  • Supports predictive back

Modal Navigation Drawer Anatomy


Component Description Active State Inactive State
Container Temporary, 280dp max width, 1dp elevation Holds active item Holds inactive items
Headline Optional header text Visible if set Visible if set
Label Text Menu item titles Highlighted with colorOnSecondaryContainer Faded with colorOnSurfaceVariant
Icon Menu item icons, 24dp Highlighted with colorOnSecondaryContainer Faded with colorOnSurfaceVariant
Active Indicator Highlights active item, rounded shape Visible, colorSecondaryContainer Not visible
Badge Label Text Optional counts/status indicators Visible if set Visible if set
Scrim Dims content, 60% opacity Visible when open Hidden when closed

Example

      
<androidx.drawerlayout.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">
    <androidx.coordinatorlayout.widget.CoordinatorLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <!-- Screen content -->
    </androidx.coordinatorlayout.widget.CoordinatorLayout>
    <com.google.android.material.navigation.NavigationView
        android:id="@+id/navigation_view"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        app:headerLayout="@layout/header_navigation_drawer"
        app:menu="@menu/navigation_drawer"/>
</androidx.drawerlayout.widget.DrawerLayout>
      
    
      
val drawerLayout = findViewById<DrawerLayout>(R.id.drawer_layout)
val navigationView = findViewById<NavigationView>(R.id.navigation_view)
topAppBar.setNavigationOnClickListener {
    drawerLayout.open()
}
navigationView.setNavigationItemSelectedListener { menuItem ->
    menuItem.isChecked = true
    drawerLayout.close()
    true
}
      
    

Adding Header

  • Add branding/info via app:headerLayout or programmatically
  • Positioned at the top of the drawer
      
<!-- res/layout/header_navigation_drawer.xml -->
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="24dp"
        android:layout_marginStart="24dp"
        android:layout_marginEnd="24dp"
        android:textAppearance="?attr/textAppearanceHeadlineSmall"
        android:textColor="?attr/colorOnSurface"
        android:text="@string/header_title"/>
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="24dp"
        android:layout_marginStart="24dp"
        android:layout_marginEnd="24dp"
        android:textAppearance="?attr/textAppearanceTitleSmall"
        android:textColor="?attr/colorOnSurfaceVariant"
        android:text="@string/header_text"/>
</LinearLayout>
      
    

Adding Dividers and Subtitles

  • Dividers auto-added between groups with unique IDs
  • Submenus treated as subtitles
      
<!-- res/menu/navigation_drawer.xml -->
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:id="@+id/main_item"
        android:title="@string/mail_subheader">
        <menu>
            <item
                android:id="@+id/search_item"
                android:icon="@drawable/ic_search_24"
                android:title="@string/search_title"
                android:checkable="true"
                app:showAsAction="ifRoom"/>
            <item
                android:id="@+id/rotation_item"
                android:icon="@drawable/ic_3d_rotation_24"
                android:title="@string/3d_title"
                android:checkable="true"
                app:showAsAction="ifRoom"/>
        </menu>
    </item>
    <item
        android:id="@+id/labels_item"
        android:title="@string/labels_subheader">
        <menu>
            <item
                android:id="@+id/label_one"
                android:icon="@drawable/ic_label_24"
                android:title="@string/label_one_title"
                android:checkable="true"
                app:showAsAction="ifRoom"/>
        </menu>
    </item>
</menu>
      
    

Attributes and Usage

Element Attribute Related Method(s) Default Value Usage Description Component Type
Container android:background setBackground ?attr/colorSurfaceContainerLow Sets container background color All
Container app:elevation setElevation 0dp (Standard), 1dp (Modal) Sets container elevation All
Header app:headerLayout inflateHeaderView, addHeaderView, getHeaderView null Sets header layout All
Item Text app:itemTextColor setItemTextColor ?attr/colorOnSecondaryContainer (active), ?attr/colorOnSurfaceVariant (inactive) Sets menu item text color All
Icon app:itemIconTint setItemIconTintList ?attr/colorOnSecondaryContainer (active), ?attr/colorOnSurfaceVariant (inactive) Sets menu item icon color All
Scrim N/A setScrimColor (DrawerLayout) Black, 60% opacity Sets scrim color (Modal only) Modal

Styles

  • NavigationView style: Widget.Material3.NavigationView
  • DrawerLayout style: Widget.Material3.DrawerLayout
  • Default theme attributes: ?attr/navigationViewStyle, ?attr/drawerLayoutStyle

Theming Navigation Drawers

  • Customize colors, typography, and shapes
  • Use res/values/styles.xml for theming

Example

      
<style name="Theme.App" parent="Theme.Material3.*">
    <item name="colorSecondaryContainer">@color/shrine_pink_100</item>
    <item name="colorOnSurfaceVariant">@color/shrine_pink_900</item>
</style>
      
    
      
<style name="Theme.App" parent="Theme.Material3.*">
    <item name="navigationViewStyle">@style/Widget.App.NavigationView</item>
</style>
<style name="Widget.App.NavigationView" parent="Widget.Material3.NavigationView">
    <item name="itemTextColor">@color/shrine_pink_900</item>
    <item name="itemShapeFillColor">@color/shrine_pink_100</item>
</style>
      
    

Material Design Documentation

  • Adheres to Material Design guidelines for Navigation Drawers
  • Covers design, behavior, theming specifications
  • Includes structure, accessibility, predictive back support
  • Refer to Material Design documentation for full details

FAQ

What are Material 3 Navigation Drawers?

  • Surfaces providing access to app destinations, deprecated for expanded navigation rails

How many variants are there?

  • Two variants: Standard and Modal

When to use a Modal Drawer?

  • Use for mobile devices with limited screen space

How to make them accessible?

  • Set contentDescription on items; ensure 48dp touch targets

Can I customize appearance?

  • Yes, theme via res/values/styles.xml

How to add dependencies?

  • Include Material Components and DrawerLayout libraries

Are there updates for the latest standards?

  • Reflects latest Material 3 standards; deprecated for expanded navigation rails

Post a Comment

Previous Post Next Post