On small screens like on mobile (setting aside how humongous smartphones tend to be nowadays), a very common pattern is to use a modal navigation drawer to allow users to navigate between one top-level destinations in the app. You’ve seen them: it’s usually the three horizontal lines on top left of an app, that can be tapped to show and hide a side drawer with a list of menu items inside of it.
Despite being a common design pattern, when I tried to learn how implement it in conjunction with the Jetpack Navigation Component, the available resources can be quite difficult to understand. They’re out there, but in my experience they’re a bit scattered and I had a hard time creating the right mental model in my mind on how to put things together.
This article is my attempt to sum things up. For things to make sense, you will need some familiarity with basic Android development and the Navigation Component itself.
Step 1: DrawerLayout
For starters, the main activity will need to use DrawerLayout as the top-level container. As the name implies, this is the layout we want to use if we want to use drawer(s) on main areas of the app. Inside the
DrawerLayout, we want to add these in order:
- A view as the first child. This view will be where the main content is shown. This can be the
NavHostFragmentlike on this guide.
However, some tutorials like this one will use
<include>here instead, to pull from a separate layout file. The separate layout file will essentially contain a
ToolBarand the fragment that will act as the
NavHostFragment. I will go with this latter implementation, since having a
ToolBaris a common requirement, and it makes sense to have it as the place to put the hide/show drawer icon. We’ll talk more about this below.
- Add the drawer as the subsequent child. We will use
<android.support.design.widget.NavigationView>for this purpose, which I’ll cover next.
Something that took me quite a bit to figure out here is the need to override the
onSupportNavigateUp() method in the main activity. Without it, the hamburger menu will not react to taps, and thus the drawer will not show up because of it. Check here for more details.
Step 2: NavigationView
Let’s focus on creating the drawer itself first. Ignoring the Navigation Component for now,
NavigationView is the standard widget for setting up the content of the modal navigation drawer. It has a few parameters to set up, two of them to focus on:
app:headerLayout: This is to pull the layout file that contains the content of the header area of the drawer.
app:menu: This is to pull the menu file that contains menu items for the navigation drawer.
Everything else about the
NavigationView is pretty straightforward.
Step 3: The main content’s layout
Speaking very generally,
MaterialToolbar is the more generic, no-fuss toolbar, while
CollapsingToolbarLayout is a toolbar layout that can start out big/tall, but then can grow smaller when the user scrolls up. Technically speaking,
CollapsingToolbarLayout is yet another wrapper, which can have
MaterialToolbar inside of it, among other things (for example an
ImageView acting as the background image of the app bar) So the choice here is more of a design decision choice.
What is CoordinatorLayout for? Broadly speaking, CoordinatorLayout is the layout to use if we want to coordinate interactions between its child views. A common example is to automatically make a FAB move up if a Snackbar is shown, so they don’t overlap. There’s some other examples with animations here. Strictly speaking CoordinatorLayout is not a requirement to connect a modal navigation drawer with the Jetpack Navigation Component, but is nice to have. Some tutorials I found use it, so we might as well have it mentioned here as well.
Step 4: NavigationUI
NavigationUI is a part of the Navigation Component that binds things together. Specifically, it is used to associate menu items in the
NavigationView, with navigation destinations as set in the Navigation Component. This is meant to simplify the navigation process and removes the requirement to manually set up click listener for each menu item. To bind the navigation view with the navigation controller, the method setupWithNavController() is used.
NavigationUI also helps with managing the top app bar, such as updating its label or modifying the top left icon and have it display the drawer icon or a back button, depending on the current destination. For the latter purpose, NavigationUI uses an object called AppBarConfiguration. To bind the toolbar and navigation controller together, the method setupWithNavController() is used.
Note here that
setupWithNavController() has several versions, with different parameters available for them, because it’s meant to be useable with different components: navigation view, toolbar, collapsing toolbar layout, or bottom navigation view. Pick the right method for the right component. For our example here, we will then need to use it twice: first for the navigation view, and second for the toolbar.
And that is all the components involved. Here’s a quick sketch that shows how everything connects:
Step 5: Resources
Below are the main tutorials and resources I’ve found that deal with this topic. Use the key points above to help make sense of them:
- Google’s Jetpack Navigation Codelabs: Navigating using menus, drawers, and bottom navigation.
- Stack Overflow question: “How to set up Navigation Component with Navigation Drawer in Android?“
- Navigation component: Update UI components with Navigation UI
- Navigation Views – Material Components for Android
- Android Design — Coordinator Layout #1: An Introduction