'Close Navigation Drawer on Back Button Pressed in Flutter

I have a material designed Navigation Drawer in my very first flutter app. This work's fine but I did't find any way to close the Navigation Drawer on Back Button Press if it's open when use WillPopScope to show AlertDialog. The application just show AlertDialog instead of close the Drawer when back press. I want Drawer should close if already open and show AlertDialog otherwise.

@override
Widget build(BuildContext context) {
  return WillPopScope(
    onWillPop: onBackPressed,
    child: Scaffold(
      appBar: AppBar(
        title: Text("Home"),
      ),
      drawer: Drawer(
      ),
      body: Center(
        child: Text("Home"),
      ),
    ),
  );
}

onBackPressed shows dialog to close the app.

Future<bool> onBackPressed() {
  return showDialog(
      barrierDismissible: false,
      context: context,
      builder: (context) => AlertDialog(
            title: Text("Do you want to exit?"),
            actions: <Widget>[
              FlatButton(
                  onPressed: () => Navigator.pop(context, false),
                  child: Text("No")),
              FlatButton(
                  onPressed: () => Navigator.pop(context, true),
                  child: Text("Yes"))
            ],
          ));
}

Can anybody guide me how can I achieve this?



Solution 1:[1]

You can copy paste run full code below
Step 1: You need Scaffold key to controll Drawer so you need GlobalKey<ScaffoldState> _key = new GlobalKey<ScaffoldState>();
Step 2: In onWillPop You can check isDrawerOpen and do Navigator.pop

code snippet

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

  MyHomePage({Key key, this.title}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return WillPopScope(
      onWillPop: () async {
        if (_key.currentState.isDrawerOpen) {
          Navigator.of(context).pop();
          return false;
        }
        return true;
      },
      child: Scaffold(

working demo

enter image description here

full code

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return WillPopScope(
      onWillPop: () async {
        print("My App Page");
        //return false;
      },
      child: MaterialApp(
        title: 'Flutter Demo',
        theme: ThemeData(
          primarySwatch: Colors.blue,
        ),
        home: MyHomePage(title: "test",),
      ),
    );
  }
}

class MyHomePage extends StatelessWidget {
  final String title;
  GlobalKey<ScaffoldState> _key = new GlobalKey<ScaffoldState>();

  MyHomePage({Key key, this.title}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return WillPopScope(
      onWillPop: () async {
        if (_key.currentState.isDrawerOpen) {
          Navigator.of(context).pop();
          return false;
        }
        return true;
      },
      child: Scaffold(
        key: _key,
        appBar: AppBar(title: Text(title)),
        body: Center(child: Text('My Page!')),
        drawer: Drawer(
          child: ListView(
            padding: EdgeInsets.zero,
            children: <Widget>[
              DrawerHeader(
                child: Text('Drawer Header'),
                decoration: BoxDecoration(
                  color: Colors.blue,
                ),
              ),
              ListTile(
                title: Text('page 2'),
                onTap: () {
                  Navigator.push(
                      context, new MaterialPageRoute(builder: (context) => Page2()));
                },
              ),
              ListTile(
                title: Text('Item 2'),
                onTap: () {
                  // Update the state of the app
                  // ...
                  // Then close the drawer
                  Navigator.pop(context);
                },
              ),
            ],
          ),
        ),
      ),
    );
  }
}


class Page2 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return WillPopScope(
      onWillPop: () async {
        print("Page2");
        _popNavigationWithResult(context, 'from_back');
        return false;
      },
      child: Scaffold(
        floatingActionButton: FloatingActionButton(
          onPressed: () {
            _popNavigationWithResult(context, 'from_button');
          },
        ),
        body: Container(
          child: Center(
            child: Text('Page 2',
                style: TextStyle(fontSize: 30.0, fontWeight: FontWeight.bold)),
          ),
        ),
      ),
    );
  }

  void _popNavigationWithResult(BuildContext context, dynamic result) {
    Navigator.pop(context, result);
  }
}

Solution 2:[2]

my Back button was not working on drawer, because of my home screen. Remove WillPopScope from drawer and put following code in the home screen instead.

WillPopScope(
  onWillPop: () async {
    return Navigator.of(context).canPop();
  },
  child: Scaffold(

Solution 3:[3]

Simply add Navigator.pop(context);

ListTile(
  title: const Text('Item 1'),
  onTap: () {
    // Update the state of the app
    // ...
    // Then close the drawer
    Navigator.pop(context);
  },
),

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Ninad Sawant
Solution 3 whoguri