The slide-in side menu — tap the hamburger, navigate, sign out — is a staple of apps with more destinations than a bottom bar can hold. Flutter makes it almost free: hand a Drawer to the Scaffold and it wires up the hamburger icon, the edge swipe, and the open/close animation for you. This guide covers adding the drawer, building a proper header, the menu items, closing the drawer on tap, the right-hand endDrawer, and opening it from a custom button, with paste-ready code.

The Complete Flutter Course: Build Android, iOS and Web apps
Go from scratch to building industry-standard apps with Riverpod, Firebase, animations, REST APIs, and more.
By Sagnik Bhattacharya and Paulina Knop
Buy nowEvery snippet below is paste-ready against current stable Flutter. The drawer is the third navigation pattern, alongside bottom navigation and tabs — reach for it when you have more destinations than fit comfortably elsewhere.
We'll add a drawer, build the header, list the menu items, close the drawer on tap, and cover endDrawer and opening from code.
If you'd rather watch a full app shell with a drawer built and themed, the channel covers these navigation structures end to end.
Add a drawer
Pass a Drawer to the Scaffold's drawer property and Flutter adds the hamburger icon and the edge swipe for free. Fill it with a ListView so it scrolls if the menu is long.
Scaffold(
appBar: AppBar(title: const Text('Coding Liquids')),
drawer: Drawer(
child: ListView(
padding: EdgeInsets.zero,
children: const [
DrawerHeader(child: Text('Menu')),
ListTile(leading: Icon(Icons.home), title: Text('Home')),
ListTile(leading: Icon(Icons.settings), title: Text('Settings')),
],
),
),
body: const HomeBody(),
)
Note padding: EdgeInsets.zero on the ListView — without it the header sits below an unwanted top gap, because ListView adds default padding inside the drawer.
A proper header
DrawerHeader gives you a styled top block, but for an account menu, UserAccountsDrawerHeader is purpose-built — it lays out an avatar, a name, and an email in the standard Material arrangement.
UserAccountsDrawerHeader(
accountName: const Text('Sagnik Bhattacharya'),
accountEmail: const Text('hello@codingliquids.com'),
currentAccountPicture: const CircleAvatar(
child: Text('S'),
),
)
This is the quickest way to a polished header. Use plain DrawerHeader with a gradient or logo when the menu isn't account-centric, and UserAccountsDrawerHeader when it is.

Build a full app navigation shell
The Complete Flutter Course wires drawers, tabs, and bottom bars into real, shipped apps.
By Sagnik Bhattacharya and Paulina Knop
Buy nowClose the drawer on tap
The open drawer is a route on the navigation stack, so a menu item must close it before — or as part of — navigating. Pop the drawer first inside the ListTile's onTap, then push the destination.
ListTile(
leading: const Icon(Icons.settings),
title: const Text('Settings'),
onTap: () {
Navigator.pop(context); // close the drawer
Navigator.pushNamed(context, '/settings');
},
)
Skip the pop and the drawer stays open over the new screen — a classic first-app bug. The pattern is always: close the drawer, then navigate, as covered in the navigation basics.
endDrawer and opening from code
The endDrawer property gives you a second drawer that opens from the right edge — handy for filters or a secondary panel. To open either drawer from your own button, call Scaffold.of(context).openDrawer() (or openEndDrawer()), making sure the context sits below the Scaffold.
Builder(
builder: (context) => IconButton(
icon: const Icon(Icons.menu),
onPressed: () => Scaffold.of(context).openDrawer(),
),
)
The Builder matters: a context taken directly in the Scaffold's own build method is above the Scaffold, so Scaffold.of can't find it. Wrapping the button in a Builder — or using a GlobalKey<ScaffoldState> — gives you a context below it.
Common mistakes
- Forgetting padding: EdgeInsets.zero. The ListView's default padding pushes the header down.
- Not popping the drawer on tap. It stays open over the destination screen.
- Scaffold.of with the wrong context. Use a
Builderor a GlobalKey so the context is below the Scaffold. - A non-scrolling Column for many items. Use a
ListViewso long menus scroll. - Overloading the drawer. For three to five primary destinations, a bottom bar is usually clearer.
Frequently asked questions
How do I add a navigation drawer in Flutter?
Pass a Drawer to the Scaffold's drawer property; Flutter adds the hamburger icon and edge swipe automatically.
How do I close the drawer when a menu item is tapped in Flutter?
Call Navigator.pop(context) in the ListTile's onTap before navigating, since the open drawer is a route on the stack.
What is the difference between drawer and endDrawer in Flutter?
drawer opens from the left as the main menu; endDrawer opens from the right for secondary panels. A Scaffold can have both.
How do I open a Flutter drawer with a custom button?
Call Scaffold.of(context).openDrawer() from a context below the Scaffold — wrap the button in a Builder or use a GlobalKey<ScaffoldState>.
Every Flutter tutorial on this site, more than 120 so far, is free and written by Sagnik Bhattacharya, founder of Coding Liquids. If you want the same ground covered as one guided path, The Complete Flutter Course at codingliquids.com wires drawers, tabs, and bottom bars into real, shipped apps.
Further reads
Keep going with the tutorials that pair with this guide:
- Flutter Development Guide 2026 — the full Flutter hub.
- Flutter Scaffold Explained — the drawer, body, and AppBar slots.
- Flutter BottomNavigationBar — the bottom-bar alternative for primary destinations.
- Flutter Navigation Basics — push, pop, and named routes.
- Flutter Card and ListTile — the items that fill the drawer menu.
Sources: Flutter documentation — Drawer, DrawerHeader, UserAccountsDrawerHeader, Scaffold.drawer and endDrawer, and the "Add a drawer to a screen" cookbook recipe (docs.flutter.dev). Verified against current stable Flutter.