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 aFuture
. It causes the route not popped if theFuture
evaulates tofalse
.
*: required