Is there a way to configure willPopScope to catch a custom pop navigation in flutter?

Viewed 2368

Is there a way to configure willPopScope to catch a custom pop navigation as follows? I have a custom Raisedbutton widget with onPressed to navigate back to the previous page.

But willPopScope doesn't catch the navigation as it does for the AppBar back button. I'm not sure if this is even possible. Please advise. Thanks!

WillPopScope(
 child: Scaffold(
  body: Container(
   child: Center(
    child: RaisedButton(
     onPressed:(){
      return Navigator.pop(context);
     },
     child: Text("Go Back),
    ),
   ),
  ),
 ),
 onWillPop: () async {
  // code to show a modal
 }
);
1 Answers

Here is a full example to achieve your goal. WillPopScope needs a maybePop call in order to do your logic:

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

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: RaisedButton(
          child: Text('Jump To Next Screen'),
          onPressed: () => Navigator.of(context)
              .push(MaterialPageRoute(builder: (_) => ModalScreen())),
        ),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }
}

class ModalScreen extends StatefulWidget {
  @override
  _ModalScreenState createState() => _ModalScreenState();
}

class _ModalScreenState extends State<ModalScreen> {
  @override
  Widget build(BuildContext context) {
    return WillPopScope(
      child: Scaffold(
        appBar: AppBar(
          leading: InkResponse(
            child: Icon(Icons.arrow_back),
            onTap: () => Navigator.of(context).maybePop(),
          ),
        ),
        backgroundColor: Colors.blue,
        body: Center(
          child: RaisedButton(
            child: Text('Let\'s go back'),
            onPressed: () {
              Navigator.of(context).maybePop();
            },
          ),
        ),
      ),
      onWillPop: () => _willPop(context),
    );
  }

  Future<bool> _willPop(BuildContext context) {
    final completer = Completer<bool>();
    showModalBottomSheet(
        context: context,
        builder: (buildContext) {
          return SizedBox(
            height: 200,
            child: Column(
              children: [
                Padding(
                  padding: const EdgeInsets.symmetric(vertical: 20),
                  child: Text('Are you sure?'),
                ),
                MaterialButton(
                    child: Text('YES'),
                    onPressed: () {
                      completer.complete(true);
                      Navigator.of(context).pop();
                    }),
                MaterialButton(
                    child: Text('NO'),
                    onPressed: () {
                      completer.complete(true);
                    }),
              ],
            ),
          );
        });

    return completer.future;
  }
}

Once you return true for your modal, you also need to Pop the screen as the modal has his own context needed to be popped.

Final result is the following:

enter image description here

Related