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:
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:
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:
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:
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:
- How to create a custom icon in Flutter, in case you need to use a custom icon.
- How to add a navigation drawer in Flutter