Skip to content

How to setup Android Navigation Drawer (2020 Updated)

So I’ve just done my first stream on Twitch, recreating an old app of mine, Dota Soundboard. During it, I found lots of confusion with setting up the navigation drawer.

Of course there was the old way with massive chunks of boilerplate, which is what I resorted to on stream until I could replace it later.

Why did I do this? Because the documentation for doing the modern navigation drawer isn’t great. So I’m hoping that this article will set that straight once and for all.

By the way, if you’re interested in a mix of programming, Tekken, and Dota content on stream, follow me on Twitch @therealpandakun.

Create your Fragments

Navigation components work through fragments. You need your home fragment, and any fragments you intend to navigate from the home fragment.

I’m gonna assume you already know how to make fragments so I’m not gonna go into detail there.

Create your menu xml

<menu xmlns:android="http://schemas.android.com/apk/res/android">

    <item
        android:id="@+id/heroes_page_fragment"
        android:title="@string/nav_heroes" />

    <item
        android:id="@+id/settings_page_fragment"
        android:title="@string/nav_settings" />

</menu>

Create an xml menu under res/menu. You don’t need your home fragment here. These are the menu items you want to have in your drawer.

Create the nav graph xmlCreate an xml navigation under res/navigation. I’ve named this one nav_graph.xml

<navigation
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/nav_graph"
    app:startDestination="@id/home_page_fragment">

    <fragment
        android:id="@+id/home_page_fragment"
        android:name="com.ericdecanini.dotasoundboard.HomeFragment">
        <action
            android:id="@+id/action_home_to_heroes"
            app:destination="@id/heroes_page_fragment" />
    </fragment>

    <fragment
        android:id="@+id/heroes_page_fragment"
        android:name="com.ericdecanini.dotasoundboard.HeroesFragment" />

</navigation>

This is your nav graph. This sets out the navigation journey your app follows. In this case, we start at the home fragment which includes the action to go to the heroes page.

What’s important here is that the ids of the fragments here match the ids of the menu items you set out earlier. After we set it up later, this will let the system make the link between the menu items and the fragments.

Write your activity xml

<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/drawerLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <androidx.fragment.app.FragmentContainerView
        android:id="@+id/nav_host_fragment"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:defaultNavHost="true"
        app:navGraph="@navigation/nav_graph" />

    <com.google.android.material.navigation.NavigationView
        android:id="@+id/navView"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:fitsSystemWindows="true"
        app:menu="@menu/menu_navigation" />

</androidx.drawerlayout.widget.DrawerLayout>

At minimum, you need to have a DrawerLayout which has a FragmentContainerView and a NavigationView. As you might guess, the FragmentContainerView is where the content of your fragments is gonna be, and the NavigationView is the drawer.

I could explain them all here but just look at the attributes above with the app namespace, those are the important bits, and quite frankly, self-explanatory.

See below if you want a version of this with a custom toolbar.

Setup the Navigation Drawer in code

private lateinit var appBarConfiguration: AppBarConfiguration

private fun setupNavigationDrawer() {
  val navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment
  val navController = navHostFragment.navController
  navView.setupWithNavController(navController)
  appBarConfiguration = AppBarConfiguration(navController.graph, drawerLayout)
  toolbar.setupWithNavController(navController, appBarConfiguration)
}

Call this function in onCreate. This creates the link between your drawer layout and nav graph, gives it a controller, and also gives the toolbar the drawer icon.

This code also ties everything together with the navigation so now, clicking on the navigation menu items will lead you to the corresponding fragment, provided you matched the names in the navigation and menu xml files.

override fun onSupportNavigateUp(): Boolean {
  val navController = findNavController(R.id.nav_host_fragment)
  return navController.navigateUp(appBarConfiguration) || super.onSupportNavigateUp()
}

Override this function too. Otherwise clicking the drawer icon will do nothing.

And just like that, you have a fully functioning navigation drawer.

Some common problems

Drawer Layout with a custom toolbar

<?xml version="1.0" encoding="utf-8"?>
<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/drawerLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <androidx.coordinatorlayout.widget.CoordinatorLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <com.google.android.material.appbar.AppBarLayout
            android:id="@+id/appBarLayout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <androidx.appcompat.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                android:background="@drawable/toolbar_bg">

                <TextView
                    style="@style/ToolbarText"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="@string/app_name" />

            </androidx.appcompat.widget.Toolbar>

        </com.google.android.material.appbar.AppBarLayout>

        <androidx.fragment.app.FragmentContainerView
            android:id="@+id/nav_host_fragment"
            android:name="androidx.navigation.fragment.NavHostFragment"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="@drawable/main_bg"
            app:layout_behavior="@string/appbar_scrolling_view_behavior"
            app:defaultNavHost="true"
            app:navGraph="@navigation/nav_graph" />

    </androidx.coordinatorlayout.widget.CoordinatorLayout>

    <com.google.android.material.navigation.NavigationView
        android:id="@+id/navView"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:background="@drawable/main_bg"
        android:layout_gravity="start"
        android:fitsSystemWindows="true"
        app:headerLayout="@layout/nav_header_main"
        app:menu="@menu/menu_navigation" />

</androidx.drawerlayout.widget.DrawerLayout>

Here’s an example. I think you can figure out the rest.

Drawer icon is dark

<style name="Theme.MyAppTheme" parent="Theme.AppCompat.NoActionBar">

Set your app theme parent accordingly.