Search code examples
flutterdartdeclarativeflutter-navigation

flutter: how to handle back button press when using navigator with pages


I am trying to implement Navigator 2.0 method. The only thing I can't make to work is the back button presses. When I press the back button, the app just exits and not going to the previous page. I tried the WillPopPage widget but back button bypassing it.

here is a sample code that doesn't work on back presses.

import 'package:flutter/material.dart';

main(List<String> args) {
  runApp(TestApp());
}

class TestApp extends StatefulWidget {
  @override
  _TestAppState createState() => _TestAppState();
}

class _TestAppState extends State<TestApp> {
  bool go = false;

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Navigator(
        pages: [
          // page 1
          MaterialPage(
            child: W1(onTapped: () {
              setState(() => go = true);
            }),
          ),
          // page 2
          if (go) MaterialPage(child: W2()),
        ],
        onPopPage: (route, result) {
          if (!route.didPop(result)) return false;
          go = false;
          return true;
        },
      ),
    );
  }
}

class W1 extends StatelessWidget {
  final void Function() onTapped;

  const W1({Key key, this.onTapped}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: FlatButton(
          onPressed: onTapped,
          child: Text("Go to second"),
        ),
      ),
    );
  }
}

class W2 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Text("pressing the back button is exiting the app.."),
      ),
    );
  }
}

I have already written a lot of code with this approach, so I can't go back to the imperative navigation anymore. How to handle the back pres with this approach?


Solution

  • This is not possible with Navigator 2.0 without extending RouterDelegate. A system back button press is handled by RouteDelegate's popRoute method. According to the docs:

    The method should return a boolean Future to indicate whether this delegate handles the request. Returning false will cause the entire app to be popped.

    The default implementation always returns false. Therefore, you must override it to handle system back button presses.

    UPDATE
    I have published an article presenting a quick and easy-to-understand guide to using Navigator 2.0. You can find it here.