flutter
/

Flutter Drawer – Complete Guide with Examples

Last Sync: Today

On this page

10
0%
5 min read
Remaining
5 minleft

Click any section to jump — progress syncs automatically

flutter

Flutter Drawer – Complete Guide with Examples

What is a Drawer in Flutter?

A Drawer is a panel that slides in from the side of a Scaffold, typically used for navigation. It is a common UI pattern in mobile apps, providing access to different screens or actions without taking up permanent screen space. In Flutter, you add a drawer by setting the drawer property of a Scaffold. The drawer usually contains a DrawerHeader and a list of ListTiles for navigation items.

Basic Drawer Implementation

DARTRead-only
1
Scaffold(
  appBar: AppBar(title: Text('Drawer Demo')),
  drawer: Drawer(
    child: ListView(
      children: [
        DrawerHeader(
          decoration: BoxDecoration(color: Colors.blue),
          child: Text('Header', style: TextStyle(color: Colors.white, fontSize: 24)),
        ),
        ListTile(
          leading: Icon(Icons.home),
          title: Text('Home'),
          onTap: () { Navigator.pop(context); },
        ),
        ListTile(
          leading: Icon(Icons.settings),
          title: Text('Settings'),
          onTap: () { Navigator.pop(context); },
        ),
      ],
    ),
  ),
)

The drawer opens when the user taps the menu icon in the app bar or swipes from the edge. Tapping a ListTile typically closes the drawer (using Navigator.pop(context)) and navigates to another screen.

DrawerHeader – Customizing the Header

DrawerHeader is a Material widget that provides a decorative header. You can put any widget inside, but it's common to use a Column with an avatar, name, and email. You can also use UserAccountsDrawerHeader for a pre‑styled header with an account switcher.

DARTRead-only
1
UserAccountsDrawerHeader(
  accountName: Text('John Doe'),
  accountEmail: Text('john@example.com'),
  currentAccountPicture: CircleAvatar(
    backgroundImage: NetworkImage('https://example.com/avatar.jpg'),
  ),
  otherAccountsPictures: [
    CircleAvatar(child: Text('A')),
  ],
)

Navigating with Drawer

To navigate to a new screen when a drawer item is tapped, you typically use Navigator.push to go to a new route. After pushing, you may want to close the drawer – either manually (by calling Navigator.pop(context)) or automatically if you're using pushReplacement (the drawer closes because the scaffold is replaced). The common pattern is:

DARTRead-only
1
ListTile(
  leading: Icon(Icons.people),
  title: Text('Profile'),
  onTap: () {
    Navigator.pop(context); // close drawer
    Navigator.push(context, MaterialPageRoute(builder: (_) => ProfilePage()));
  },
)

Closing the Drawer Programmatically

The drawer closes automatically when you call Navigator.pop(context). If you need to close it from a deeper widget, you can use the Scaffold state: Scaffold.of(context).closeDrawer(). However, that's only available if you have a Scaffold ancestor. Alternatively, you can use the Navigator.pop(context) from anywhere inside the drawer's widget tree.

DARTRead-only
1
// Inside a child of the drawer
ElevatedButton(
  onPressed: () => Navigator.pop(context),
  child: Text('Close'),
)

Customizing Drawer Appearance

You can customize the drawer's width, background color, and shape using the Drawer widget's properties. The Drawer itself is a Material widget, so you can set its elevation, color, and shape.

DARTRead-only
1
Drawer(
  elevation: 16.0,
  backgroundColor: Colors.grey.shade100,
  shape: RoundedRectangleBorder(
    borderRadius: BorderRadius.only(topRight: Radius.circular(20), bottomRight: Radius.circular(20)),
  ),
  child: ...,
)

Adding a Scrollable Drawer

If the drawer content is too tall, wrap it in a ListView. The Drawer itself is a Material that can contain any widget; ListView provides scrolling.

DARTRead-only
1
drawer: Drawer(
  child: ListView(
    padding: EdgeInsets.zero,
    children: [
      DrawerHeader(...),
      ...List.generate(20, (index) => ListTile(title: Text('Item $index'))),
    ],
  ),
)

Common Mistakes

    • Forgetting to close the drawer: After navigating, the drawer stays open unless you call Navigator.pop(context).
    • Using Scaffold.of(context) without a Scaffold ancestor: In the drawer's builder, Scaffold.of(context) returns the correct scaffold because the drawer is inside the scaffold's tree. However, if you're inside a separate widget, ensure you have a BuildContext with a Scaffold ancestor.
    • Not handling large content: Without a ListView, the drawer may overflow.
    • Using a Drawer without a Scaffold: The drawer only works as a child of Scaffold.
    • Not providing unique keys for list items: If you have dynamic items, use Key to preserve state.

Best Practices

    • Use DrawerHeader or UserAccountsDrawerHeader for a consistent header.
    • For navigation items, use ListTile with an icon and text.
    • After navigation, always close the drawer (Navigator.pop(context)).
    • For long drawers, wrap content in a ListView.
    • Use const for static widgets to improve performance.

Key Takeaways

    • A drawer is added via the drawer property of Scaffold.
    • The drawer typically contains a DrawerHeader and a list of ListTiles.
    • Use Navigator.pop(context) to close the drawer.
    • Customize width, color, and shape with Drawer properties.
    • Wrap content in a ListView if it might exceed the screen height.

Try it yourself

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Drawer Demo',
      home: HomePage(),
    );
  }
}

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Drawer Example')),
      drawer: Drawer(
        child: ListView(
          padding: EdgeInsets.zero,
          children: [
            DrawerHeader(
              decoration: BoxDecoration(
                gradient: LinearGradient(
                  colors: [Colors.blue, Colors.purple],
                ),
              ),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  CircleAvatar(
                    radius: 30,
                    backgroundImage: NetworkImage('https://via.placeholder.com/150'),
                  ),
                  SizedBox(height: 10),
                  Text('User Name', style: TextStyle(color: Colors.white, fontSize: 20)),
                  Text('user@example.com', style: TextStyle(color: Colors.white70)),
                ],
              ),
            ),
            ListTile(
              leading: Icon(Icons.home),
              title: Text('Home'),
              onTap: () {
                Navigator.pop(context);
                // Navigate or just show a snackbar
                ScaffoldMessenger.of(context).showSnackBar(
                  SnackBar(content: Text('Home selected')),
                );
              },
            ),
            ListTile(
              leading: Icon(Icons.settings),
              title: Text('Settings'),
              onTap: () {
                Navigator.pop(context);
                ScaffoldMessenger.of(context).showSnackBar(
                  SnackBar(content: Text('Settings selected')),
                );
              },
            ),
            Divider(),
            ListTile(
              leading: Icon(Icons.info),
              title: Text('About'),
              onTap: () {
                Navigator.pop(context);
                ScaffoldMessenger.of(context).showSnackBar(
                  SnackBar(content: Text('About selected')),
                );
              },
            ),
          ],
        ),
      ),
      body: Center(
        child: Text('Swipe from left or tap the menu icon'),
      ),
    );
  }
}

Test Your Knowledge

Q1
of 4

Which property of Scaffold is used to add a drawer?

A
sideMenu
B
drawer
C
navigationDrawer
D
menu
Q2
of 4

How do you close the drawer programmatically?

A
Scaffold.of(context).closeDrawer()
B
Navigator.pop(context)
C
Drawer.close()
D
Both A and B are valid
Q3
of 4

Which widget is commonly used as the header of a drawer?

A
DrawerHeader
B
AppBar
C
ListTile
D
Container
Q4
of 4

How can you add a drawer that slides from the right side?

A
endDrawer
B
rightDrawer
C
trailingDrawer
D
sideDrawer

Frequently Asked Questions

How do I open the drawer programmatically?

Use the ScaffoldState: Scaffold.of(context).openDrawer(). You must have a Scaffold ancestor and ensure the context is below it. Alternatively, use a GlobalKey<ScaffoldState>.

How do I show a drawer on the right side?

Use the endDrawer property of Scaffold instead of drawer. It slides from the right side. The behavior is otherwise identical.

Can I have both a drawer and an end drawer?

Yes, you can set both drawer and endDrawer. The end drawer slides from the right.

How do I change the drawer width?

Wrap the Drawer in a SizedBox with a specified width. However, the drawer's width is usually set by the system's edge swipe detection. To override, you may need to use a custom ModalDrawer or Drawer with constraints. The simplest is to set the Drawer's child to a SizedBox with a width, but that may not respect the edge swipe area. For full control, consider using a custom Drawer implementation.

Why does my drawer close when I tap outside?

That's the default behavior – tapping outside the drawer or swiping the screen dismisses it. You can control this by wrapping the drawer in a WillPopScope if you need to intercept, but it's rarely necessary.

Previous

flutter bottom navigation bar

Next

flutter tabbar

Related Content

Need help?

Explore our comprehensive docs or start a chat with our tech experts.