Flutter - Disable/Override Back Button with WillPopScope

Do you need to disable or override the back button in your Flutter application? Find out in this tutorial.

By default, when the user presses back either using the device's physical or soft key or using the back button on the AppBar, the application will navigate back to the previous screen or quit if it's the last screen in the stack. In other word, the back button by default pops the top screen in the stack.

If you need to disable that behavior, you can do it easily. Flutter provides WillPopScope that allows you to control the behavior when the user presses back. This tutorial assumes you have already understood how to navigate between screens in Flutter.

Disabling Back Navigation

For using WillPopScope, there are two important and required properties. The first is child which represents the screen widget on which you want the back button disabled. The second is onWillPop which is a callback that returns a Future. If the Future resolves to false, the screen will not be popped. However, the screen can still be popped using Navigator.pop(context).

Below is an example. From HomeScreen, you can open SecondScreen. The back button is disabled on SecondScreen, but there is a button for going back to HomeScreen.

  import 'package:flutter/material.dart';
  
  void main() => runApp(MyApp());
  
  class MyApp extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
      return MaterialApp(
        initialRoute: '/',
        routes: {
          '/': (context) => HomeScreen(),
          '/second': (context) => SecondScreen(),
        },
      );
    }
  }
  
  class HomeScreen extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
      return Scaffold(
        appBar: AppBar(
          title: Text('Home Screen'),
        ),
        body: Center(
          child: RaisedButton(
            child: Text('Go to second screen'),
            onPressed: () {
              Navigator.pushNamed(context, '/second');
            },
          ),
        ),
      );
    }
  }
  
  class SecondScreen extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
      return new WillPopScope(
        onWillPop: () async => false,
        child: Scaffold(
          appBar: AppBar(
            title: Text("Second Screen"),
          ),
          body: Center(
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                crossAxisAlignment: CrossAxisAlignment.center,
                children: <Widget>[
                  RaisedButton(
                    child: Text('Back'),
                    onPressed: () {
                      Navigator.pop(context);
                    },
                  ),
                ],
              )
          ),
        ),
      );
    }
  }
  

Overriding Back Navigation

You can also add something to do inside the onWillPop callback to define what should happen when the back button is pressed. For example, you can display a toast message.

  class SecondScreen extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
      return new WillPopScope(
        onWillPop: () async {
          Fluttertoast.showToast(
              msg: 'Some text',
              toastLength: Toast.LENGTH_SHORT,
              gravity: ToastGravity.BOTTOM,
              timeInSecForIos: 1,
          );
  
          return false;
        },
        child: Scaffold(
          appBar: AppBar(
            title: Text("Second Screen"),
          ),
          body: Center(
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                crossAxisAlignment: CrossAxisAlignment.center,
                children: <Widget>[
                  RaisedButton(
                    child: Text('Back'),
                    onPressed: () {
                      Navigator.pop(context);
                    },
                  ),
                ],
              )
          ),
        ),
      );
    }
  }
  

WillPopScope Properties

Below are the available properties you can pass in the constructor.

  • Key key: The widget key, used to control if it's should be replaced.
  • Widget child*: The widget below this widget in the tree.
  • WillPopCallback onWillPop*: A callback which returns a Future. It causes the route not popped if the Future evaulates to false.

*: required