Skip to content
FlutterDocs

How to Make ʺDouble Press Back Button to Exitʺ in Flutter

Verified Solution Tested on Flutter 3.47.7 • Dart 3.13.5
Jump to Updated Flutter Example ↓

In this example, we are going to show you how to make double press the back button to exit the app on Flutter. We are not going to use any package to achieve this feature. See the example below:

See this also:\u00a0How to override Back Button and Show Exit Confirm in Flutter App

Double Back Button Press Exist App Example:

import 'package:flutter/material.dart';

void main() {
  runApp(MaterialApp( 
      home: MyApp()
  ));
}

class MyApp extends StatefulWidget{
  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {

  var ctime;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
          body: WillPopScope(

             onWillPop: () {
                DateTime now = DateTime.now();
                if (ctime == null || now.difference(ctime) > Duration(seconds: 2)) { 
                     //add duration of press gap
                    ctime = now;
                    ScaffoldMessenger.of(context).showSnackBar(
                       SnackBar(content: Text('Press Back Button Again to Exit')) 
                    ); //scaffold message, you can show Toast message too.
                    return Future.value(false);
                }

                return Future.value(true);
             },

             child: Container( 
                color: Colors.lightBlue,
                //your content goes here.
             )
          )
      );
  }
}

Output on Back button Press:

How to Make ʺDouble Press Back Button to Exitʺ in Flutter illustration

In this way, you can add a Double back button press to exit feature on Flutter App. For an alternative exit pattern using confirmation alerts, see overriding the back button with a confirmation popup and displaying toast messages on back press.

Updated Flutter Example
SDK: Flutter 3.47.7 • Dart 3.13.5 Verified on Flutter 3.47.7 (Stable)

Updated Flutter Example

Modern PopScope Exit Interception Architecture

Key Implementation Details & Modern Differences:

  • PopScope Migration: Replaces completely deprecated WillPopScope (deprecated in Flutter 3.12, removed from modern patterns) with Flutter's official PopScope and onPopInvokedWithResult.
  • Predictive Back Support: Respects Android 14+ predictive back gestures by declaring predictive navigation intention via dynamic canPop boolean flags.
  • Micro-Confirmation Ergonomics: Displays an ephemeral Material 3 SnackBar on the initial gesture, allowing pop only when a second back event occurs within a 2-second time window.
Updated Flutter Example Code
import 'package:flutter/material.dart';

void main() {
  runApp(const MaterialApp(home: ModernDoubleBackExitDemo()));
}

class ModernDoubleBackExitDemo extends StatefulWidget {
  const ModernDoubleBackExitDemo({super.key});

  @override
  State<ModernDoubleBackExitDemo> createState() =>
      _ModernDoubleBackExitDemoState();
}

class _ModernDoubleBackExitDemoState extends State<ModernDoubleBackExitDemo> {
  DateTime? _lastBackPressed;
  bool _canPop = false;

  void _handlePopInvoked(bool didPop, dynamic result) {
    if (didPop) return;

    final now = DateTime.now();
    final backPressedRecently =
        _lastBackPressed != null &&
        now.difference(_lastBackPressed!) < const Duration(seconds: 2);

    if (backPressedRecently) {
      setState(() => _canPop = true);
      // Allow pop on subsequent invocation
      WidgetsBinding.instance.addPostFrameCallback((_) {
        if (mounted) {
          Navigator.of(context).maybePop(result);
        }
      });
    } else {
      _lastBackPressed = now;
      ScaffoldMessenger.of(context).showSnackBar(
        const SnackBar(
          content: Text('Press back again to exit'),
          duration: Duration(seconds: 2),
        ),
      );
    }
  }

  @override
  Widget build(BuildContext context) {
    return PopScope(
      canPop: _canPop,
      onPopInvokedWithResult: _handlePopInvoked,
      child: Scaffold(
        appBar: AppBar(title: const Text('Modern PopScope Exit Interception')),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              const Icon(Icons.exit_to_app, size: 48, color: Colors.blueAccent),
              const SizedBox(height: 16),
              const Text(
                'Press device back button twice within 2 seconds to exit.',
                textAlign: TextAlign.center,
              ),
              const SizedBox(height: 20),
              FilledButton(
                onPressed: () => _handlePopInvoked(false, null),
                child: const Text('Simulate Back Navigation'),
              ),
            ],
          ),
        ),
      ),
    );
  }
}
Document History & Archival Record

Original reference snapshot archived February 3, 2023. Updated working solution verified on modern Flutter & Dart SDKs.