5

I've implemented a Drawer in my Flutter app.

Closed Drawer:

enter image description here

Opened Drawer:

enter image description here

As you can see, the Drawer is on top of the Appbar. Before I started the app on Flutter, we had a native Android app with a Drawer that used to look like this:

Closed Drawer:

enter image description here

Opened Drawer:

enter image description here

Here is my code:

class MyDrawer extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return _buildDrawer(context);
  }
}

Widget _buildDrawer(BuildContext context) {
  return new Drawer(
    child: new ListView(
      children: <Widget>[
        _buildDrawerItem(context, EnumDrawerItem.PROJECT_SELECTION, Icons.home, Colors.transparent),
        new Divider(height: 20.0),
        _buildDrawerItem(context, EnumDrawerItem.TASK_LIST, Icons.home, Colors.transparent),
        new Divider(),
        _buildDrawerItem(context, EnumDrawerItem.GUIDED_TASKS, Icons.home, Colors.transparent),
        new Divider(),
        _buildDrawerItem(context, EnumDrawerItem.PHOTOS, Icons.home, Colors.transparent),
        new Divider(),
        _buildDrawerItem(context, EnumDrawerItem.DOCUMENTS, Icons.home, Colors.transparent),
        new Divider(),
        _buildDrawerItem(context, EnumDrawerItem.LOG_OUT, Icons.home, const Color(0x85bf0202)),
        new Divider(),
      ],
    ),
  );
}

Widget _buildDrawerItem(BuildContext context, EnumDrawerItem drawerItem, IconData iconData, Color color) {
  return  Container(
    color: color,
    child: new Padding(
      padding: new EdgeInsets.all(7.0),
      child: new Row(
        children: <Widget>[
          new Icon(iconData),
          new Container(
            margin: new EdgeInsets.fromLTRB(10.0, 0.0, 0.0, 0.0),
            child: new Text(
              drawerItem.toString(),
              style: styleDrawerItem,
            ),
          ),
        ],
      ),
    ),
  );
}

I know this is the standard Material Design style, but the client wants it as it was before.

Would it be possible to implemented it as in the 2 last screenshots? Do you have any idea?

Ale
  • 2,282
  • 5
  • 38
  • 67

4 Answers4

20

Wrap your main Scaffold in another Scaffold and use the drawer of child Scaffold also make sure to set automaticallyImplyLeading to false so you don't get back icon in the AppBar

UPDATE : i don't recommend this way because of this issue

return Scaffold(
      primary: true,
      appBar: AppBar(
        title: Text("Parent Scaffold"),
        automaticallyImplyLeading: false,
      ),
      body: Scaffold(
        drawer: Drawer(),
      ),
    );

Final Result :

enter image description here

Raouf Rahiche
  • 28,948
  • 10
  • 85
  • 77
  • thanks a lot for taking the time to help me. One last question: would it be possible to keep the `Drawer` icon in the `Appbar`? As you can see, there is a `drawer` icon when it's closed, and a back arrow when it is opened. Thanks! – Ale Jul 27 '18 at 07:47
  • 1
    yes you can play with icon in the parent AppBar As you want using the Leading property and as i mentioned in my answer if you want the icon set automaticallyImplyLeading to true – Raouf Rahiche Jul 27 '18 at 07:51
  • 1
    Alright I'll give it a try. Thank you I really appreciate your help :) – Ale Jul 27 '18 at 08:06
  • I've removed the `automaticallyImplyLeading` property in the `AppBar`. Now I get the back arrow when the `Drawer` is opened but no icon when the `Drawer` is closed :( can you please check the gif? http://recordit.co/IdRFflKuEH – Ale Jul 27 '18 at 08:41
  • try to provide a default icon using the leading property – Raouf Rahiche Jul 27 '18 at 08:49
11

I use the key in scaffold and references in leading in scaffold principal how in the example

GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey();

return Scaffold(
  appBar: AppBar(
      title: Text('Draw'),
      leading: IconButton(
          icon: Icon(Icons.dehaze),
          onPressed: () {
            if (_scaffoldKey.currentState.isDrawerOpen == false) {
              _scaffoldKey.currentState.openDrawer();
            } else {
              _scaffoldKey.currentState.openEndDrawer();
            }
          })),
  body: Scaffold(
    key: _scaffoldKey,
    drawer: Drawer(),
    body: Center(
      child: Text('Drawer'),
    ),
  ),
);
Jaime
  • 179
  • 2
  • 3
6

Try this one:

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    var statusBarHeight = MediaQuery.of(context).padding.top;
    var appBarHeight = kToolbarHeight;  //this value comes from constants.dart and equals to 56.0
    return Scaffold(
      drawerScrimColor: Colors.transparent,
      appBar: AppBar(),
      drawer: Container(
        padding: EdgeInsets.only(top: statusBarHeight+ appBarHeight + 1),//adding one pixel for appbar shadow
        width: MediaQuery.of(context).size.width,
        child: Drawer(),//write your drawer code
      ),
      body: AnyBody(), //add your body
      bottomNavigationBar: AnyNavigationBar(), //add your navigation bar
    );
  }
}
  • Don't trigger MediaQuery in your HomePage builder function, it will rebuild everything by every change on MediaQuery values and will reduce the performance. better to move your Container into a custom widget and use MediaQuery on it's build function – Mahmoud_Mehri Jan 21 '22 at 09:32
4

Simple and to the point:

drawer: Padding(
    padding: const EdgeInsets.fromLTRB(0, 80, 0, 0),
    child: Drawer(),
Ali Punjabi
  • 452
  • 4
  • 19