How to write a double back button pressed to exit app using flutter

This is an example of my code (I've used "fluttertoast" for showing toast message, you can use snackbar or alert or anything else)

DateTime currentBackPressTime;

@override
Widget build(BuildContext context) {
  return Scaffold(
    ...
    body: WillPopScope(child: getBody(), onWillPop: onWillPop),
  );
}

Future<bool> onWillPop() {
    DateTime now = DateTime.now();
    if (currentBackPressTime == null || 
        now.difference(currentBackPressTime) > Duration(seconds: 2)) {
      currentBackPressTime = now;
      Fluttertoast.showToast(msg: exit_warning);
      return Future.value(false);
    }
    return Future.value(true);
  }

You can try this package.

Inside a Scaffold that wraps all your Widgets, place the DoubleBackToCloseApp passing a SnackBar:

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: DoubleBackToCloseApp(
          child: Home(),
          snackBar: const SnackBar(
            content: Text('Tap back again to leave'),
          ),
        ),
      ),
    );
  }
}

The solution below must be considered deprecated because it causes a few issues that were tackled in the package mentioned. For instance, the app closes if the snack bar was dismissed by the user (see hcbpassos/double_back_to_close_app#2).

Old answer

You can also opt for a solution involving SnackBar. It's not as simple as Andrey Turkovsky's answer, but it's quite more elegant and you won't depend on a library.

class _FooState extends State<Foo> {
  static const snackBarDuration = Duration(seconds: 3);

  final snackBar = SnackBar(
    content: Text('Press back again to leave'),
    duration: snackBarDuration,
  );

  DateTime backButtonPressTime;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      // The BuildContext must be from one of the Scaffold's children.
      body: Builder(
        builder: (context) {
          return WillPopScope(
            onWillPop: () => handleWillPop(context),
            child: Text('Place your child here'),
          );
        },
      ),
    );
  }

  Future<bool> handleWillPop(BuildContext context) async {
    final now = DateTime.now();
    final backButtonHasNotBeenPressedOrSnackBarHasBeenClosed =
        backButtonPressTime == null ||
            now.difference(backButtonPressTime) > snackBarDuration;

    if (backButtonHasNotBeenPressedOrSnackBarHasBeenClosed) {
      backButtonPressTime = now;
      Scaffold.of(context).showSnackBar(snackBar);
      return false;
    }

    return true;
  }
}

Tags:

Dart

Flutter