Pinkesh Darji I love to solve problems using technology that improves users' lives on a major scale. Over the last seven-plus years, I've been developing and leading various mobile apps in different areas.

How to add a navigation drawer in Flutter

4 min read 1373

How To Add A Navigation Drawer In Flutter

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.

Swiping Drawer Open And Closed

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:

When to use a navigation drawer

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.

How to add a basic navigation drawer in Flutter

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:

We made a custom demo for .
No really. Click here to check it out.

  1. Make sure you are using the MaterialApp
  2. Inside the Scaffold, add the Drawer property and assign the Drawer widget
  3. Inside the Drawer widget, add the ListView as a child widget
  4. Inside the ListView, add the DrawerHeader widget. This will create a material design drawer header
  5. Inside the DrawerHeader, add a Text widget with some text
  6. Below the DrawerHeader, add a ListTile widget with an icon and title that represents a single page
  7. Similarly add other ListTile for other pages

Code 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:

Basic Navigation Drawer

Here’s how the code is translated into design:

Basic Navigation Drawer Code

Displaying user details in navigation drawer header

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:

  1. In the example code above, just replace the DrawerHeader widget with the UserAccountsDrawerHeader
  2. Add the accountName parameter and set the username
  3. Add the accountEmail parameter and set the user email
  4. Add the currentAccountPicture parameter and set the logged user’s profile picture

Code 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:

Opening Drawer From The Right Side

Displaying AboutListTile

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:

  1. Add the AboutListTile widget at the end and inside the ListView (where you have ListTile items for the pages)
  2. Inside the AboutListTile, add the icon and child parameters and add the Text widget inside the child
  3. Inside the AboutListTile, add the applicationName parameter and provide the app name
  4. Inside the AboutListTile, add the applicationVersion parameter and provide the current app version

Code 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:

Displaying AboutListTile

Opening navigation drawer programmatically

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:

  1. First, create the global variable in your class
  2. Inside the Scaffold widget, add the key parameter and assign the global key
  3. Add the ElevatedButton to your page
  4. Inside the ElevatedButton, add the onPressed() method and call the openDrawer() method using the Global key

Code 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:

Opening Drawer Programmatically

Opening a navigation drawer from the right side

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.

Opening Drawer From The Right Side

Controlling navigation drawer width

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:

  1. Wrap the existing Drawer widget inside the Container widget
  2. Inside the Container 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 width

Code 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:

Controlling Drawer Width

Conclusion

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.

: Full visibility into your web apps

LogRocket is a frontend application monitoring solution that lets you replay problems as if they happened in your own browser. Instead of guessing why errors happen, or asking users for screenshots and log dumps, LogRocket lets you replay the session to quickly understand what went wrong. It works perfectly with any app, regardless of framework, and has plugins to log additional context from Redux, Vuex, and @ngrx/store.

In addition to logging Redux actions and state, LogRocket records console logs, JavaScript errors, stacktraces, network requests/responses with headers + bodies, browser metadata, and custom logs. It also instruments the DOM to record the HTML and CSS on the page, recreating pixel-perfect videos of even the most complex single-page apps.

.
Pinkesh Darji I love to solve problems using technology that improves users' lives on a major scale. Over the last seven-plus years, I've been developing and leading various mobile apps in different areas.

Leave a Reply