The navigation drawer in Flutter allows users to navigate to different pages of your app. The navigation drawer is added using the Drawer widget. It can be opened via swipe gesture or by clicking on the menu icon in the app bar.
Typically, the navigation drawer opens up from the left side of the screen, but you can also configure it to open from the right side (for the LTR text settings). When it opens, the drawer covers almost 60–70 percent of the screen, and to close it, you can simply swipe or click outside the drawer.
In this tutorial, we’ll learn how to add the navigation drawer in Flutter.
Here’s what we’ll cover:
If you’re a visual learner, check out this quick video tutorial:
Drawer (Flutter Widget of the Week)
Need to provide navigation to other pages? Try using a Drawer! Learn more about Drawer → https://goo.gle/2MhwExx Learn everything about Flutter at → https://goo.gle/2WAhEN1 Get more tips! → https://goo.gle/307BX6t This video is also subtitled in Chinese, Indonesian, Italian, Japanese, Korean, Portuguese, and Spanish. Subscribe! → http://goo.gle/FlutterYT
The navigation drawer can be used as an alternate option to the TabBar widget. It is recommended to use a navigation drawer when you have at least five pages to navigate. If your app has several pages, providing the navigation inside the TabBar makes for a less intuitive user experience.
To add a basic navigation drawer in Flutter, you must first use MaterialApp
in your project. Then, the Drawer widget can be added to the Scaffold widget.
Here are the step-by-step instructions:
MaterialApp
Scaffold
, add the Drawer
property and assign the Drawer
widgetDrawer
widget, add the ListView
as a child widgetListView
, add the DrawerHeader
widget. This will create a material design drawer headerDrawerHeader
, add a Text
widget with some textDrawerHeader
, add a ListTile
widget with an icon
and title
that represents a single pageListTile
for other pagesCode example:
@override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( centerTitle: true, title: const Text( 'Navigation Drawer', ), backgroundColor: const Color(0xff764abc), ), drawer: Drawer( child: ListView( // Important: Remove any padding from the ListView. padding: EdgeInsets.zero, children: [ const DrawerHeader( decoration: BoxDecoration( color: Colors.blue, ), child: Text('Drawer Header'), ), ListTile( leading: Icon( Icons.home, ), title: const Text('Page 1'), onTap: () { Navigator.pop(context); }, ), ListTile( leading: Icon( Icons.train, ), title: const Text('Page 2'), onTap: () { Navigator.pop(context); }, ), ], ), ), body: Center( child: Column( children: [ SizedBox( height: 50, ), ], ), ), ); }
Output:
Here’s how the code is translated into design:
The basic example above shows the drawer header with simple text, but in a real-world scenario, you may want to display the current user information inside the drawer header. You can do that with the help of a ready-made widget called UserAccountsDrawerHeader.
The UserAccountsDrawerHeader is used to display all user-related information, such as profile picture, username, and email. You can also open the user details page when users tap on the user information.
To display user details in the navigation drawer:
DrawerHeader
widget with the UserAccountsDrawerHeader
accountName
parameter and set the usernameaccountEmail
parameter and set the user emailcurrentAccountPicture
parameter and set the logged user’s profile pictureCode example:
return Scaffold( appBar: AppBar( centerTitle: true, title: const Text( 'Navigation Drawer', ), backgroundColor: const Color(0xff764abc), ), drawer: Drawer( child: ListView( // Important: Remove any padding from the ListView. padding: EdgeInsets.zero, children: [ const UserAccountsDrawerHeader( // <-- SEE HERE decoration: BoxDecoration(color: const Color(0xff764abc)), accountName: Text( "Pinkesh Darji", style: TextStyle( fontWeight: FontWeight.bold, ), ), accountEmail: Text( "[email protected]", style: TextStyle( fontWeight: FontWeight.bold, ), ), currentAccountPicture: FlutterLogo(), ), ListTile( leading: Icon( Icons.home, ), title: const Text('Page 1'), onTap: () { Navigator.pop(context); }, ), ListTile( leading: Icon( Icons.train, ), title: const Text('Page 2'), onTap: () { Navigator.pop(context); }, ), ], ), ), body: Center( child: Column( children: [ SizedBox( height: 50, ), ], ), ), );
Output:
Sometimes, you may need to show additional information about the app, like its version, privacy policy, official website, etc. Flutter has a dedicated widget called AboutListTile   that you can display inside the navigation drawer.
To display the AboutListTile
inside the drawer:
AboutListTile
widget at the end and inside the ListView
(where you have ListTile
items for the pages)AboutListTile
, add the icon
and child
parameters and add the Text
widget inside the child
AboutListTile
, add the applicationName
parameter and provide the app nameAboutListTile
, add the applicationVersion
parameter and provide the current app versionCode example:
Drawer( child: ListView( // Important: Remove any padding from the ListView. padding: EdgeInsets.zero, children: [ const UserAccountsDrawerHeader( decoration: BoxDecoration(color: const Color(0xff764abc)), accountName: Text( "Pinkesh Darji", style: TextStyle( fontWeight: FontWeight.bold, ), ), accountEmail: Text( "[email protected]", style: TextStyle( fontWeight: FontWeight.bold, ), ), currentAccountPicture: FlutterLogo(), ), ListTile( leading: Icon( Icons.home, ), title: const Text('Page 1'), onTap: () { Navigator.pop(context); }, ), ListTile( leading: Icon( Icons.train, ), title: const Text('Page 2'), onTap: () { Navigator.pop(context); }, ), AboutListTile( // <-- SEE HERE icon: Icon( Icons.info, ), child: Text('About app'), applicationIcon: Icon( Icons.local_play, ), applicationName: 'My Cool App', applicationVersion: '1.0.25', applicationLegalese: '© 2019 Company', aboutBoxChildren: [ ///Content goes here... ], ), ], ), )
Output:
Sometimes, you may also want to open or close the drawer programmatically. For example, if you are developing an onboarding feature or letting the user know how to navigate your app, you may want to open the navigation drawer when the user clicks on UI elements that are part of the onboarding feature, such as the next button, open button, etc.
To open the navigation drawer programmatically:
Scaffold
widget, add the key
parameter and assign the global keyElevatedButton
to your pageElevatedButton
, add the onPressed()
method and call the openDrawer()
method using the Global keyCode example:
class NavigationDrawerDemo extends StatefulWidget { const NavigationDrawerDemo({Key? key}) : super(key: key); @override State<NavigationDrawerDemo> createState() => _NavigationDrawerDemoState(); } class _NavigationDrawerDemoState extends State<NavigationDrawerDemo> { final GlobalKey<ScaffoldState> _key = GlobalKey(); // Create a key @override Widget build(BuildContext context) { return Scaffold( key: _key, appBar: AppBar( centerTitle: true, title: const Text( 'Navigation Drawer', ), backgroundColor: const Color(0xff764abc), ), drawer: Drawer( child: ListView( // Important: Remove any padding from the ListView. padding: EdgeInsets.zero, children: [ ListTile( leading: Icon( Icons.home, ), title: const Text('Page 1'), onTap: () { Navigator.pop(context); }, ), ListTile( leading: Icon( Icons.train, ), title: const Text('Page 2'), onTap: () { Navigator.pop(context); }, ), ], ), ), body: Center( child: Column( children: [ SizedBox( height: 50, ), ElevatedButton( onPressed: () { _key.currentState!.openDrawer(); //<-- SEE HERE }, child: const Text( 'Elevated Button 1', style: TextStyle(fontSize: 24), ), ), ], ), ), ); } }
Output:
In very rare cases, you may want to open the drawer from the right side. To do so, simply replace the drawer
parameter (inside the Scaffold) with the endDrawer
and you are done.
When the navigation drawer opens, by default, it will cover more than 50 percent of the screen. You can change this and allow the navigation drawer to occupy a space that you define.
To set the width of the navigation drawer:
Drawer
widget inside the Container
widgetContainer
widget, add the width
parameter and assign the percent of the screen you want the navigation drawer to cover using the MediaQuery
. For example, the MediaQuery.of(context).size.width * 0.5
will allow the navigation drawer to open until it reaches 50 percent of the screen’s widthCode example:
drawer: Container( width: MediaQuery.of(context).size.width * 0.5, //<-- SEE HERE child: Drawer( child: ListView( // Important: Remove any padding from the ListView. padding: EdgeInsets.zero, children: [ ListTile( leading: Icon( Icons.home, ), title: const Text('Page 1'), onTap: () { Navigator.pop(context); }, ), ], ), ), ),
Output:
In this tutorial, we learned how to add the navigation drawer in Flutter with practical examples. We first saw how to add a basic navigation drawer and then gradually moved toward customizing the drawer. Finally, we learned how to open the navigation drawer programmatically and control its width.
Install LogRocket via npm or script tag. LogRocket.init()
must be called client-side, not
server-side
$ npm i --save logrocket // Code: import LogRocket from 'logrocket'; LogRocket.init('app/id');
// Add to your HTML: <script src="https://cdn.lr-ingest.com/LogRocket.min.js"></script> <script>window.LogRocket && window.LogRocket.init('app/id');</script>
Hey there, want to help make our blog better?
Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.
Sign up nowCompare Prisma and Drizzle ORMs to learn their differences, strengths, and weaknesses for data access and migrations.
It’s easy for devs to default to JavaScript to fix every problem. Let’s use the RoLP to find simpler alternatives with HTML and CSS.
Learn how to manage memory leaks in Rust, avoid unsafe behavior, and use tools like weak references to ensure efficient programs.
Bypass anti-bot measures in Node.js with curl-impersonate. Learn how it mimics browsers to overcome bot detection for web scraping.