Flutter Drawer – A Step-by-Step Guide

As a navigation menu grows, its rows may need more room than the screen provides. A Flutter drawer is a panel that slides in from the edge of a Scaffold and holds navigation choices.

I’ll show how to make the menu scroll and update the visible page when someone selects a destination.

What a Flutter drawer does

A Flutter drawer is a Material panel that slides in from the edge of a Scaffold to hold navigation choices. Set the Scaffold’s drawer property, and its AppBar supplies a menu button while Scaffold handles the edge-swipe gesture.

The drawer is temporary navigation, not the page itself. Your app still owns which destination is selected and what content appears after a tap.

WidgetJob in this example
ScaffoldOwns the drawer and page layout
DrawerProvides the side panel
ListViewLets the menu scroll when it is taller than the screen
ListTileDisplays a destination and responds to a tap

Prerequisites for the example

  • Use a Flutter project with the Flutter SDK installed.
  • Configure a device or emulator before launching the app.
  • Replace the starter code in lib/main.dart with the complete example below.

Step 1: Attach the drawer to Scaffold

Start with the page and its drawer together. Keeping the selected destination in the page state means a menu tap can update the visible content before the drawer closes.

import 'package:flutter/material.dart';

void main() {
  runApp(const DrawerDemoApp());
}

class DrawerDemoApp extends StatelessWidget {
  const DrawerDemoApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Drawer demo',
      theme: ThemeData(useMaterial3: true),
      home: const HomePage(),
    );
  }
}

class HomePage extends StatefulWidget {
  const HomePage({super.key});

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  int _selectedIndex = 0;

  static const _destinations = <String>[
    'Home',
    'Projects',
    'Settings',
  ];

  void _selectDestination(int index) {
    setState(() {
      _selectedIndex = index;
    });
    Navigator.pop(context);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Drawer demo')),
      drawer: Drawer(
        child: ListView(
          padding: EdgeInsets.zero,
          children: [
            const DrawerHeader(
              decoration: BoxDecoration(color: Colors.indigo),
              child: Align(
                alignment: Alignment.bottomLeft,
                child: Text(
                  'Workspace',
                  style: TextStyle(color: Colors.white, fontSize: 24),
                ),
              ),
            ),
            for (var index = 0; index < _destinations.length; index++)
              ListTile(
                leading: Icon(_iconFor(index)),
                title: Text(_destinations[index]),
                selected: index == _selectedIndex,
                onTap: () => _selectDestination(index),
              ),
          ],
        ),
      ),
      body: Center(
        child: Text('Selected page: ${_destinations[_selectedIndex]}'),
      ),
    );
  }

  IconData _iconFor(int index) {
    switch (index) {
      case 0:
        return Icons.home;
      case 1:
        return Icons.folder;
      default:
        return Icons.settings;
    }
  }
}

Step 2: Build a menu that can scroll

ListView lets the menu scroll when its items are taller than the available screen. EdgeInsets.zero removes its default inset, and DrawerHeader gives the destinations a clear starting point.

The screenshot shows the open state, with a header and menu rows above the dimmed page.

Flutter app with its navigation drawer open, showing a header and menu rows
An open Flutter drawer with a header and navigation rows.

Step 3: Select a destination and close the drawer

A ListTile can show a selected state, but the app must track which destination is active. Here, _selectedIndex stores that choice, and the selected property reads it.

ActionEffect
Set _selectedIndex in setStateThe page rebuilds with the chosen destination active
Call Navigator.pop(context)The drawer closes

Verify the navigation flow

Run the app on a configured device or emulator, open the AppBar menu button, and choose each destination. The drawer should close after a choice, the page label should match it, and reopening the drawer should highlight the same choice.

  • Open the AppBar menu button and confirm Home is selected.
  • Tap Projects and confirm the page label and selected row change.
  • Reopen the drawer and confirm the selection remains highlighted.

Handle menu overflow and Material 3 choices

When destinations no longer fit vertically, a fixed Column can overflow, so use ListView to make the drawer scroll. NavigationDrawer offers indexed destination selection for Material 3 apps.

WidgetUse it for
DrawerA temporary panel with custom content or simple menu rows
NavigationDrawerA Material 3 component with indexed destination selection

Keep navigation state with the page

If the selected destination must outlive this page, connect the menu to the app’s routing layer instead of keeping the index only in this widget. Run the sample from its project directory:

flutter run

Flutter drawer questions

How does a Flutter drawer open?

When a Drawer is assigned to Scaffold.drawer, the AppBar normally displays a button that opens it. Scaffold also handles the edge-swipe gesture unless that behavior is disabled.

How do I close a Flutter drawer after a menu tap?

Call Navigator.pop(context) from the ListTile callback after applying the selected destination. ScaffoldState.closeDrawer is another documented close method.

How can a Flutter drawer menu scroll?

Use a ListView as the Drawer child. It can scroll when its content is taller than the available screen height.

Should I use Drawer or NavigationDrawer?

Drawer is a side panel commonly used with Scaffold. Flutter documents NavigationDrawer as a Material 3 destination-oriented alternative with indexed selection callbacks.

Sushant Dhiman
Sushant Dhiman

Sushant Dhiman writes beginner-friendly Flutter and Dart tutorials covering widgets, layouts, navigation, dialogs, and state. He also covers Node.js, Express, and jQuery fundamentals.

Articles: 14