Custom Drawer in Flutter
How to add a custom drawer to your mobile screen in Flutter.
While creating mobile applications, there are two primary options for navigation: Tabs and Drawers. When there is insufficient space to support tabs, drawers provide a handy alternative.
In this blog, I will create a simple application that will demonstrate how to implement a drawer widget and how to customize it according to your design.
Let’s dirty our hand with coding by practically implementing the drawer widget in flutter.
In Flutter, use the drawer widget in combination with a Scaffold to create a layout with Material Design drawer.
Code Example
Firstly, I will create a new project by name of “flutter_drawer”. And clear all the boilerplate comments and code to make it clear and easy to understandable. And create new class SimpleDrawerScreen in simple_drawer_screen.dart file and pass it to the Material() home property. It will look something like this.
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: SimpleDrawerScreen(),
);
}
}
Create a Scaffold
To add a drawer to the app, wrap it in a Scaffold widget. The scaffold supports special Material Design components, such as Drawers, AppBars and SnackBars.
return Scaffold(
appBar: AppBar(),
drawer: // Add a Drawer here in the next step.
);
Add a drawer
Now we will add the drawer widget to the Scaffold. You can pass any widget to the drawer, Like Container or SizedBox and customize it later, but it is often best to use the drawer widget from the library, which adheres to the Material Design spec.
return Scaffold(
drawer: Drawer(
child: // Populate the Drawer in the next step.
),
);
Add Items to the Drawer
Now we have a drawer in place, add content to it. We will add a ListView as a child to the Drawer. While you could use a Column widget. ListView is handy because it ensures the user can scroll through the options in the drawer if there isn’t enough vertical space to fit everything.
Drawer(
child: ListView(
// Remove any padding from the ListView.
padding: EdgeInsets.zero,
children: [
const DrawerHeader(
decoration: BoxDecoration(
color: Colors.blue,
),
child: Text('Drawer Header'),
),
ListTile(
title: const Text('Item 1'),
onTap: () {
// Update the state of the app.
// ...
},
),
ListTile(
title: const Text('Item 2'),
onTap: () {
// Update the state of the app.
// ...
},
),
],
),
);
Output
When you run, the above code will create a simple and basic drawer like this.
Customize Drawer
Now let’s add some functionality to the Drawer, like we said, Navigation to the new screen and customization of its UI.
Our final customize drawer will look something like this. I will also share its whole source code at the end of this article.
Drawer Header
Now let’s create our own custom header of the drawer, where we show the user information and when click on it will redirect to the user profile screen.
/// Header of the Drawer
Material(
color: Colors.blueAccent,
child: InkWell(
onTap: (){
/// Close Navigation drawer before
Navigator.pop(context);
Navigator.push(context, MaterialPageRoute(builder: (context) => UserProfile()),);
},
child: Container(
padding: EdgeInsets.only(
top: MediaQuery.of(context).padding.top,
bottom: 24
),
child: Column(
children: const[
CircleAvatar(
radius: 52,
backgroundImage: NetworkImage(
'https://images.unsplash.com/photo-1554151228-14d9def656e4?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxzZWFyY2h8MTB8fHNtaWx5JTIwZmFjZXxlbnwwfHwwfHw%3D&auto=format&fit=crop&w=500&q=60'
),
),
SizedBox(height: 12,),
Text('Sophia',
style: TextStyle(
fontSize: 28,
color: Colors.white
),),
const Text('@sophia.com',
style: TextStyle(
fontSize: 14,
color: Colors.white
),),
],
),
),
),
),
Drawer Menu List
In Drawer menu list is very important, where we show different options, like settings, profile etc. when clicking on these options it will redirect to the destined screen.
/// Header Menu items
Column(
children: [
ListTile(
leading: Icon(Icons.home_outlined),
title: Text('Home'),
onTap: (){
/// Close Navigation drawer before
Navigator.pop(context);
Navigator.push(context, MaterialPageRoute(builder: (context) => HomeScreen()),);
},
),
ListTile(
leading: Icon(Icons.favorite_border),
title: Text('Favourites'),
onTap: (){
/// Close Navigation drawer before
Navigator.pop(context);
Navigator.push(context, MaterialPageRoute(builder: (context) => FavouriteScreen()),);
},
),
ListTile(
leading: Icon(Icons.workspaces),
title: Text('Workflow'),
onTap: (){},
),
ListTile(
leading: Icon(Icons.update),
title: Text('Updates'),
onTap: (){},
),
const Divider(color: Colors.black45,),
ListTile(
leading: Icon(Icons.account_tree_outlined),
title: Text('Plugins'),
onTap: (){},
),
ListTile(
leading: Icon(Icons.notifications_outlined),
title: Text('Notifications'),
onTap: (){},
),
],
)
Full Code of Customized Drawer
class CustomizeDrawerScreen extends StatelessWidget {
const CustomizeDrawerScreen({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
appBar: AppBar(
title: Text('Customize Drawer'),
),
drawer: Drawer(
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
/// Header of the Drawer
Material(
color: Colors.blueAccent,
child: InkWell(
onTap: (){
/// Close Navigation drawer before
Navigator.pop(context);
Navigator.push(context, MaterialPageRoute(builder: (context) => UserProfile()),);
},
child: Container(
padding: EdgeInsets.only(
top: MediaQuery.of(context).padding.top,
bottom: 24
),
child: Column(
children: const[
CircleAvatar(
radius: 52,
backgroundImage: NetworkImage(
'https://images.unsplash.com/photo-1554151228-14d9def656e4?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxzZWFyY2h8MTB8fHNtaWx5JTIwZmFjZXxlbnwwfHwwfHw%3D&auto=format&fit=crop&w=500&q=60'
// 'https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxzZWFyY2h8Mnx8c21pbHklMjBmYWNlfGVufDB8fDB8fA%3D%3D&auto=format&fit=crop&w=500&q=60'
),
),
SizedBox(height: 12,),
Text('Sophia',
style: TextStyle(
fontSize: 28,
color: Colors.white
),),
const Text('@sophia.com',
style: TextStyle(
fontSize: 14,
color: Colors.white
),),
],
),
),
),
),
/// Header Menu items
Column(
children: [
ListTile(
leading: Icon(Icons.home_outlined),
title: Text('Home'),
onTap: (){
/// Close Navigation drawer before
Navigator.pop(context);
Navigator.push(context, MaterialPageRoute(builder: (context) => HomeScreen()),);
},
),
ListTile(
leading: Icon(Icons.favorite_border),
title: Text('Favourites'),
onTap: (){
/// Close Navigation drawer before
Navigator.pop(context);
Navigator.push(context, MaterialPageRoute(builder: (context) => FavouriteScreen()),);
},
),
ListTile(
leading: Icon(Icons.workspaces),
title: Text('Workflow'),
onTap: (){},
),
ListTile(
leading: Icon(Icons.update),
title: Text('Updates'),
onTap: (){},
),
const Divider(color: Colors.black45,),
ListTile(
leading: Icon(Icons.account_tree_outlined),
title: Text('Plugins'),
onTap: (){},
),
ListTile(
leading: Icon(Icons.notifications_outlined),
title: Text('Notifications'),
onTap: (){},
),
],
)
],
),
),
);
),
);
}
}
Note: I highly recommend giving a read to the flutter official documentation about the Drawer, it is very helpful. Doc
Source Code:
To access the full source code, this is my GitHub repo.
Your contribution
👏 Press the clap button below to show your support and motivate me to write better!
💬 Leave a response to this article by providing your insights, comments or wishes for the series.
📢 Share this article with your friends, colleagues on social media.
➕ Follow me on Medium.
⭐ Follow me on Github.