79

After I tap an item in the Scaffold's drawer I want it to automatically hide itself. How do I do it in Flutter?

DogeLion
  • 3,371
  • 5
  • 16
  • 24

13 Answers13

116

Navigator.pop() will pop the Drawer route off the stack and cause it to close.

Collin Jackson
  • 110,240
  • 31
  • 221
  • 152
  • 2
    But this means I need to add this call to every onTap handler, right? – DogeLion May 05 '17 at 15:12
  • 1
    Yeah. You could refactor the call to `pop` into a shared private method if the code duplication bothers you. – Collin Jackson May 07 '17 at 16:19
  • 1
    So, if I want open a new route at the same time, I have to close the drawer first and then push another. the drawer works a really dumb way. LOL. I have thought the drawer as a widget of scaffold, but it seems that I'm definitely wrong. :( – Neal.Marlin Dec 01 '18 at 09:18
  • 2
    I am sorry, but `Navigator.pop()` does not close the drawer in my case... (neither do `Navigator.pop(context)` or `Navigator.pop(context, true)` do so.... What do I need to do in order to close the drawer by selecting one of its items ? My Drawer is inside a Scaffold inside a MaterialApp... does this matter maybe ?? – iKK Feb 17 '19 at 11:47
  • It seems that the MaterialApp indeed caused a problem (since the context was missing). I found a solution [from this link...](https://stackoverflow.com/a/49374128/3826232) – iKK Feb 18 '19 at 09:19
44

First create a ScaffoldState key

GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();

Scaffold(
  key: _scaffoldKey,)

Now you can open and close the drawer using the toggleDrawer() method.

for the left drawer

toggleDrawer() async {
  if (_scaffoldKey.currentState.isDrawerOpen) {
    _scaffoldKey.currentState.openEndDrawer();
  } else {
    _scaffoldKey.currentState.openDrawer();
  }
}

for the right drawer

toggleDrawer() async {
  if (_scaffoldKey.currentState.isDrawerOpen) {
    _scaffoldKey.currentState.openDrawer();
  } else {
    _scaffoldKey.currentState.openEndDrawer();
  }
}
Bholendra Singh
  • 980
  • 7
  • 14
  • 5
    i feel this is the best answer to programaticaly manage the drawer – Lakshman Pilaka Apr 20 '20 at 09:52
  • How does this close drawer? – cocacrave Jun 12 '20 at 03:33
  • 1
    Great solution but it should be noted that this does not work for the drawer if it is placed on the "right" side. `Scaffold(endDrawer: Drawer())` – Matthew Nov 06 '20 at 19:20
  • @Matthew for endDrawer toggleDrawer() async { if (_scaffoldKey.currentState.isDrawerOpen) { _scaffoldKey.currentState.openDrawer(); } else { _scaffoldKey.currentState.openEndDrawer(); } } – Bholendra Singh Mar 29 '21 at 19:05
  • for right side drawer if (_scaffoldKey.currentState!.isEndDrawerOpen) { _scaffoldKey.currentState!.openDrawer(); } else { _scaffoldKey.currentState!.openEndDrawer(); } – Omar Faruq Jul 07 '21 at 11:03
  • Doesn't work with pushing named routes as it say's the key is being used multiple times. – Oliver Dixon Oct 10 '22 at 11:40
37

Navigator.of(context).pop() should do what you want :)

https://docs.flutter.io/flutter/widgets/Navigator-class.html https://docs.flutter.io/flutter/material/Drawer-class.html

Hadrien Lejard
  • 5,644
  • 2
  • 21
  • 18
35

Shorthand for closing the drawer and navigating to a new route:

Navigator.popAndPushNamed(context, '/newroute');

Assaf S.
  • 4,676
  • 2
  • 22
  • 18
19

If you simply want to close the Drawer, you can use any of the following:

Navigator.pop(context);
Navigator.of(context).pop();

And if you want to navigate to a new page, you can use

Navigator.popAndPushNamed(context, "/new_page");

or

Navigator.pop(context);
Navigator.push(context, MaterialPageRoute(builder: (_) => Page2()));
CopsOnRoad
  • 237,138
  • 77
  • 654
  • 440
6

For the lastest Flutter version (v0.3.2 when I am writing this), the implementation changed a bit and Navigator.pop() now requires a given context.

Navigator.pop(context) is the typical usage for closing a route.
Navigator.pop(context, true) is the usage for closing a route with a returned result.

See Drawer Class and example on Flutter's Cookbook.

Yann Masoch
  • 1,628
  • 1
  • 15
  • 20
5

This is the answer

First in Class

GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();

Second In Widget

 Scaffold(key: _scaffoldKey,)

Third in code

if (_scaffoldKey.currentState.isDrawerOpen) {
  _scaffoldKey.currentState.openEndDrawer();
}
Yassine Chilali
  • 377
  • 4
  • 9
3

I think what the OP is possibly trying to say is that even though Navigator.of(context).pop() and Navigator.pop(context) should work, they aren't in his case- I'm having the same issue.

Early on in a project the drawer works as it should - opening and closing properly. Since several changes have been made (none directly to the drawer or its scaffold) the drawer is no longer closing with Navigator.of(context).pop() and Navigator.pop(context).

I did a little more digging and found that instead of using Navigator.pop you can use Scaffold.of(context).openEndDrawer to close the drawer - even though it doesn't seem like it should. I've never used this function until now but it works perfectly. Hope this helps anyone with the same issue.

Chris
  • 1,720
  • 16
  • 35
  • 1
    ```Scaffold.of(context).openEndDrawer``` will open the end drawer so while opening the enddrawer, it probably closes the current drawer,it will get your work done but its not the right way to do that, – Mahesh Jamdade May 06 '20 at 14:16
1

You can use the below code according to your requirement.

When you want to remove and push new route:

Navigator.of(context).popAndPushNamed('/routeName');

When you want to just pop:

Navigator.of(context).pop();
Bhavesh Patel
  • 596
  • 4
  • 17
1

First Pop widget, after that Push your route it will automatically close the Drawer when you come back next time.

Navigator.pop(context); // Widget will be poped
Navigator.pushNamed(context, '/routename'); // New Route will be pushed
0

Well its quite Easy

Problem Statement : In default Home Page when someone presses back button , (if drawer is open) it is closed, else a prompt is thrown asking for Exit Application "Yes" and "No".

Solution

  1. Add

    GlobalKey _scaffoldKey = new GlobalKey();

  2. Make Function Future _onWillPop() async handling the required problem statement

  3. Call key and onWillPop as given in the below source code

See Through full source code For the additions done related to this problem statement in source code

import 'package:flutter/material.dart';

class HomePage extends StatefulWidget {
  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();

  Future<bool> _onWillPop() async {
    if(_scaffoldKey.currentState != null && _scaffoldKey.currentState!.isDrawerOpen){
      return true;
    }
    return (await showDialog(
          context: context,
          builder: (context) => new AlertDialog(
            title: new Text('Leaving our App?'),
            content: new Text('Are you sure you want to Exit?'),
            actions: <Widget>[
              TextButton(
                onPressed: () => Navigator.of(context).pop(false),
                child: new Text('No'),
              ),
              TextButton(
                onPressed: () => Navigator.of(context).pop(true),
                child: new Text('Yes'),
              ),
            ],
          ),
        )) ??
        false;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      key: _scaffoldKey,
      body: WillPopScope(
        onWillPop: _onWillPop,
        child: Container(
          child: Center(
            child: Text("Welcome My App"),
          ),
        ),
      ),
      drawer: SideDrawer(),
    );
  }
}
0
 ListTile(
              title: Text(
                'Notification Setting',
                style: TextStyle(
                    fontSize: 16.0, color: HexColor(HexColor.gray_text)),
              ),
              leading: Icon(
                Icons.notifications_outlined,
                size: 24.0,
                color: HexColor(HexColor.primarycolor),
              ),
              onTap: () {

                _scaffoldKey.currentState?.openEndDrawer();
                Navigator.push(context, MaterialPageRoute(builder: (context) {
                  return NotificationSettingActivity();
                }
                ));
              },
            ),
sarjeet singh
  • 461
  • 4
  • 10
-1

Navigate.of(context).pop(); OR
Navigate.pop(contex);

must be the first in onTap() function

for example :

 onTap: () {
 Navigator.of(context).pop();//before pushing to any other route 
 Navigator.push(
 context,
 MaterialPageRoute(
 builder: (BuildContext context) => Screen2(),
   ),
  );
 }
Arun A
  • 21
  • 2
  • Welcome to Stack Overflow and thank you for your answer. However, this is really a duplicate, since the accepted answer is already to use Navigator.pop(). It feels like you are trying to answer some of the commenters who said that it didn't work for them, and that would be better done in a comment when you have that privilege. – NotTheDr01ds Dec 26 '20 at 16:30