Flutter: Creating Drawers

Flutter: Creating Drawers

Daksh Gupta
ProAndroidDev
Published in
7 min readJun 12, 2018

--

Flutter is a mobile App SDK by Google which helps in creating modern mobile apps for iOS and Android using a single(almost) code base. It’s a new entrant in the cross platform mobile application development and unlike other frameworks like React Native, it doesn’t use JavaScript but DART as a Programming Language.

It’s highly recommended to read my first post “Flutter: From Zero To Comfortable” to get a good sense of how Flutter widgets work and what’s going on here in this post.

What is a Drawer?

A drawer is an invisible side screen which generally contain menu items and occupies around half of the screen when displayed. If you’ve ever used apps like Twitter and/or GMail, you already know what I’m talking about.

Creating Empty Drawer

Let’s first create an empty drawer. As with other flutter applications with material design, we’ll be creating a basicMaterialApp , the home of which shall contain a Scaffold with Drawer

Here is how the code for basic MaterialApp shall look like

class MyApp extends StatelessWidget {
@override
Widget build (BuildContext ctxt) {
return new MaterialApp(
home: new DWidget()
);
}
}

The DWidget here is the widget which will contain drawers. It should be noted that drawers are part of Scaffold along with appBar and body . Once we add drawer to the Scaffold, it generates a three line menu item on the top left corner of the application bar, which on clicking displays the drawer screen.

Here is how the basic code shall look like.

class DWidget extends StatelessWidget {
@override
Widget build (BuildContext ctxt) {
return new Scaffold(
drawer: new Drawer(
child: new Text("\n\n\nDrawer Is Here"),
),
appBar: new AppBar(
title: new Text("Drawer Demo"),
),
body: new Text("Drawer Body"),
);
}
}

This will create an app with a bare minimum drawer as displayed below.

An empty drawer

As you might have noticed that drawer, takes child: and not children: , which means at any point of time we can have only one widget inside drawer.

To have more than one widget, we need to use widgets which are capable of holding multiple child widgets like Column . Here is how the drawer code will look with Column

drawer: new Drawer(
child: new Column(
children: <Widget>[
new Text("\n\n\n\Drawer Is Here => 1"),
new Text("Drawer Is Here => 2"),
new Text("Drawer Is Here => 3"),
],
)
),

This will display three lines of text in the drawer.

Adding Drawer Header

Now we know what drawers are and how it can be created. However, if we go ahead and compare our drawers with GMail or Twitter Drawer, we’ll notice that the drawers always come with a header which takes approximately ~20% space atthe top.

In flutter, we can create a similar header using DrawerHeader widget which takes a child and allows us to decorate the header. In here, I’m using BoxDecoration so that we can distinguish the complete boundary of the widget.

Here is how the code with DrawerHeader shall look like

drawer: new Drawer(
child:new DrawerHeader(
child: new Text("DRAWER HEADER.."),
decoration: new BoxDecoration(
color: Colors.orange
),
)
),

And here is how the existing drawer changes

Drawer with Drawer Header

It must be surprising to see header taking the 100% of the drawer whereas it was suppose to take only around 20% of the space on top.

This happens because within the drawer child, we only have DrawerHeader and nothing else.

Moving Drawer Header to the Top

To move the drawer header on top of the drawer, we need to use the widgets which can contain multiple widgets (e.g. children:) like Column on ListView .

We’re going to use ListView over here as the Column doesn’t take all the available space evenly, which will leave patches of empty space onthe screen. Here is how we can use the ListView inside the Drawer

drawer: new Drawer(
child: new ListView(
children: <Widget>[
new DrawerHeader(
child: new Text("DRAWER HEADER.."),
decoration: new BoxDecoration(
color: Colors.orange
),
)
],
)
),

And here is how the resulting app shall look like

Drawer with ListView Widget

Now, this is what we were looking for. This also resembles the apps like GMail and Twitter drawer header.

Now, we can decorate the header the way we want and have as many items and links as possible.

I’ll come back to decorating headers in some later posts, in this post we’ll proceed ahead with finishing the functionality of drawer and add some actionable items

Adding Actionable Items in Drawer

Since we want some actions to be performed when someone selects(or taps) one the items of the drawer, we need to use widgets which can handle onTap method, or alternatively we need to create a container around widgets to handle gestures.

However, using widgets with in-built onTap handler is preferred over here because of its ease of use.

One such widget which we can use inside the ListView is ListTile

Let’s create couple of items using ListTile and add corresponding actions using onTap() method.

There are many actions we can add on onTap(), however, most often we’ll end up loading a new page with onTap()

Loading new Pages

I’ve explained how to load new pages in my another Flutter article called Flutter: Creating Multi Page Application with Navigation .

I’ll highly recommend reading this article to understand how navigation works in flutter. We’ll be using the same method over here to load a new Page onto the screen.

In here, we’ll create a couple of pages (i.e. widgets) and load them as a result of an action from end users on drawers

class FirstPage extends StatelessWidget {
@override
Widget build(BuildContext ctxt) {
return new Scaffold(
appBar: new AppBar(title: new Text("First Page"),),
body: new Text("I belongs to First Page"),
);
}
}

class SecondPage extends StatelessWidget {
@override
Widget build(BuildContext ctxt) {
return new Scaffold(
appBar: new AppBar(title: new Text("Second Page"),),
body: new Text("I belongs to Second Page"),
);
}
}

Let’s load them as onTap() action on ListTile . Here is how the complete drawer code shall look like

drawer: new Drawer(
child: new ListView(
children: <Widget>[
new DrawerHeader(
child: new Text("DRAWER HEADER.."),
decoration: new BoxDecoration(
color: Colors.orange
),
),
new ListTile(
title: new Text("Item => 1"),
onTap: () {
Navigator.push(ctxt,
new MaterialPageRoute(builder: (ctxt) => new FirstPage()));
},
),
new ListTile(
title: new Text("Item => 2"),
onTap: () {
Navigator.push(ctxt,
new MaterialPageRoute(builder: (ctxt) => new SecondPage()));
},
),
],
)
),

And here is how the actions will look like on the app

Drawer with Actionable Items

Making Drawer Disappear

We’ve successfully able to load the new pages on click of drawer items, however, when we try to come back on the original page, the drawer remains loaded there (as can be seen in the picture above).

This is annoying as we don’t want the drawers to remain there unless we explicitly load it again

This can be achieved by unloading the drawer before we load a new page by calling Navigator.pop() . Here is how the onTap() code shall be changed

onTap: () {
Navigator.pop(ctxt);
Navigator.push(ctxt,
new MaterialPageRoute(builder: (ctxt) => new FirstPage()));
},

And the resultant screen will not keep the drawers on the original Page

Making Drawer Disappear

Making Drawer available across all Pages

We generally create common actions on drawers which which should be made available across the whole application. This can be done by making sure that the drawers are available to each Scaffold or all the pages.

This effectively means that we can have drawer code in a separate stateless widget as

class DrawerOnly extends StatelessWidget {
@override
Widget build (BuildContext ctxt) {
return new Drawer(
child: new ListView(
children: <Widget>[
new DrawerHeader(
child: new Text("DRAWER HEADER.."),
decoration: new BoxDecoration(
color: Colors.orange
),
),
new ListTile(
title: new Text("Item => 1"),
onTap: () {
Navigator.pop(ctxt);
Navigator.push(ctxt,
new MaterialPageRoute(builder: (ctxt) => new FirstPage()));
},
),
new ListTile(
title: new Text("Item => 2"),
onTap: () {
Navigator.pop(ctxt);
Navigator.push(ctxt,
new MaterialPageRoute(builder: (ctxt) => new SecondPage()));
},
),
],
)
);
}
}

and use this inside our widgets with Scaffold

class DWidget extends StatelessWidget {
@override
Widget build (BuildContext ctxt) {
return new Scaffold(
drawer: new DrawerOnly(), // New Line
appBar: new AppBar(
title: new Text("Drawer Demo"),
),
body: new Text("Drawer Body"),
);
}
}

class FirstPage extends StatelessWidget {
@override
Widget build(BuildContext ctxt) {
return new Scaffold(
drawer: new DrawerOnly(), // new Line
appBar: new AppBar(title: new Text("First Page"),),
body: new Text("I belongs to First Page"),
);
}
}

class SecondPage extends StatelessWidget {
@override
Widget build(BuildContext ctxt) {
return new Scaffold(
drawer: new DrawerOnly(), // New Line
appBar: new AppBar(title: new Text("Second Page"),),
body: new Text("I belongs to Second Page"),
);
}
}

And the resulting app will have drawers on all the pages

Drawer on all pages

That’s all for this particular post. I hope I was able to explain how we can create and use drawers in flutter applications.

Thanks for reading….!!!

Daksh

--

--

🔹Software Product Development Consultant, Trainer, & Coach🔹 Tech Speaker & Content Creator 🔹 youtube.com/@Cognitive-Programmer 🔹 linkedin.com/in/iDaksh