Flutter - Change Drawer Icon Examples

This tutorial shows you how to change the icon of a navigation drawer in Flutter.

Some mobile applications use a navigation drawer for navigating between pages. We already have a tutorial on how to add a drawer in Flutter. By default, the icon will be a menu icon which consists of 3 horizontal bars, also known as the hamburger icon. However, it's possible to replace it with any icon you want. In this tutorial, I am going to show you how to change the icon, including how to change the size and the color.

Change Drawer Icon

As you already know, you can add a drawer in a Flutter application by a widget as the drawer argument of the Scaffold widget. If the Scaffold also has an AppBar, a default icon for opening the drawer will be shown on the AppBar. If you want to replace the default one, you can pass a widget as the leading argument of the AppBar.

Besides replacing the widget, you have to make the new icon works for opening the drawer. It doesn't open the drawer by default, so you have to handle the click event by yourself. To make an icon that's clickable, you can use an IconButton. Then, pass a function as the onPressed argument of the IconButton which will be called when the user clicks the button.

Inside the function, you need to add a code for opening the drawer. It can be done by using the ScaffoldState's openDrawer method. You can get the current ScaffoldState by calling Scaffold.of(context). The passed context object must be the correct BuildContext. Let's take a look at the example below.

  Widget build(BuildContext context) {
    return Scaffold(
      leading: IconButton(
        tooltip: MaterialLocalizations.of(context).openAppDrawerTooltip,
        icon: const Icon(
          Icons.label,
        ),
        onPressed: () {
          Scaffold.of(context).openDrawer();
        },
      ),
    );
  }

In the code above, you cannot use that BuildContext. That's because the BuildContext refers to a parent widget above the Scaffold widget. The Scaffold.of method works by finding a ScaffoldState from the closest instance of this class that encloses the given context. Because the context above is created before the Scaffold widget is built, it will not find the ScaffoldState. As a solution, you can wrap the icon inside a Builder widget. With Builder, it becomes possible to get the context from the current build method.

Based on the explanation above, we can create a custom icon for the navigation drawer like in the code below.

  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        leading: Builder(
          builder: (BuildContext context) {
            return IconButton(
              icon: const Icon(
                Icons.label,
              ),
              onPressed: () {
                Scaffold.of(context).openDrawer();
              },
            );
          },
        ),
        title: const Text('Woolha.com Flutter Tutorial'),
        backgroundColor: Colors.teal,
      ),
      drawer: const MyDrawer(),
      body: const Center(
        child: Text('Woolha.com'),
      ),
    );
  }

Output:

Flutter - Custom Drawer Icon

Change Size

To change the size of the icon, pass a size argument to the IconButton.

  IconButton(
    iconSize: 40,
    icon: const Icon(
      Icons.label,
    ),
    // other arguments
  )

Output:

Flutter - Custom Drawer Icon Size

Change Color

You can set the color by passing a color argument to the IconButton.

  IconButton(
    color: Colors.yellow,
    icon: const Icon(
      Icons.label,
    ),
    // other arguments
  )

Output:

Flutter - Custom Drawer Icon Color

Set Tooltip

Optionally, you can add a tooltip to the icon. The MaterialLocalizations class already defines a getter named openAppDrawerTooltip which is appropriate for this case.

  IconButton(
    tooltip: MaterialLocalizations.of(context).openAppDrawerTooltip,
    icon: const Icon(
      Icons.label,
    ),
    // other arguments
  )

Output:

Flutter - Custom Drawer Icon Tooltip

Full Code

  import 'package:flutter/material.dart';

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

  class MyApp extends StatelessWidget {

    const MyApp({Key? key}) : super(key: key);

    @override
    Widget build(BuildContext context) {
      return const MaterialApp(
        title: 'Woolha.com Flutter Tutorial',
        home: NavigationDrawerExample(),
      );
    }
  }

  class NavigationDrawerExample extends StatelessWidget {

    const NavigationDrawerExample({super.key});

    @override
    Widget build(BuildContext context) {
      return Scaffold(
        appBar: AppBar(
          leading: Builder(
            builder: (BuildContext context) {
              return IconButton(
                iconSize: 40,
                color: Colors.yellow,
                tooltip: MaterialLocalizations.of(context).openAppDrawerTooltip,
                icon: const Icon(
                  Icons.label,
                ),
                onPressed: () {
                  Scaffold.of(context).openDrawer();
                },
              );
            },
          ),
          title: const Text('Woolha.com Flutter Tutorial'),
          backgroundColor: Colors.teal,
        ),
        drawer: const MyDrawer(),
        body: const Center(
          child: Text('Woolha.com'),
        ),
      );
    }
  }

  class MyDrawer extends StatelessWidget {

    const MyDrawer({super.key});

    @override
    Widget build(BuildContext context) {
      return Drawer(
        // width: 150,
        child: ListView(
          padding: EdgeInsets.zero,
          children: [
            const DrawerHeader(
              child: Center(
                child: Text('Woolha.com'),
              ),
            ),
            ListTile(
              title: const Text('To-do List'),
              leading: const Icon(Icons.list),
              onTap: () {
                Navigator.pop(context);
              },
            ),
          ],
        ),
      );
    }
  }

Summary

Replacing the default navigation drawer icon can be done by passing a widget as the leading argument of the Scaffold widget. The passed widget needs to handle the event when the user clicks on it, therefore using an IconButton can be a suitable solution. Since calling the method for opening the drawer requires a correct BuildContext, you need to wrap the widget in a Builder widget.

You can also read about: