How To: Flutter App Exit Prompt

Fighting the cognitive miser one toast at a time

Itumeleng Masuluke
Flutter Community
4 min readJul 22, 2020

--

Photo by Dustin Tramel on Unsplash

You know what really grinds my gears? The myriad of times I mistakenly exit an app because I pressed the back button one too many times. You know what else really grinds my gears? That there have also been times when I would mistakenly exit and app, reopen it and then mistakenly close it again (usually when I resume youtube into a video I was previously watching and feel like the back button should pop me out of the video and not out of the app). Maybe this isn’t a shared experience, maybe everyone else pays better attention to what the stack count is whenever they open an app or maybe everyone just writes it off as a necessary evil that every app user must endure.

Disclaimer

We are going to be adding a function in the “navigator.dart” file. If your anxiety won’t let you passed the “Non-Project File Protection” dialog may I suggest creating a backup of the file just to put your mind at ease? You can also just revert the changes from your flutter repo should anything malfunction, which is highly unlikely.

Desired Outcome

To start it off lets set the stage, we’ll begin with a fresh flutter app. What we inevitably want to do is check the stack count whenever a page is removed and show the dialog when the user is trying to remove the last page in the stack. To make this easier we’ll create a generic component that we can reuse and attach a “WillPopScope” widget to. we also create a function of type Future<bool> which we will put our logic in later.

Next, we adjust our MyHomePageState class, we remove the scaffold and everything in it and return an instance of “ScreenHolder” instead. We also add a GlobalKey which we can pass to our “ScreenHolder” to uniquely identify each instance.

I created a second class called MySecondPage which is basically a clone of MyHomepage without the floatingActionButton. You can navigate to any page this is just to test that the pop up only shows up when we remove the last page in the stack.

Editing Navigator.dart

Okay so now we’ve set the stage and can get to the main code. The first thing we want to do is open “navigator.dart”. We can do this but pressing ctrl + clicking on any Navigator definition (Works for android studio not sure about vs code). This is a good time to mention I’m using “flutter_linux_1.17.3-stable” and _history’s data type is List<_RouteEntry>, I know some previous versions used List<Route<dynamic>>, use the same data type that is used in the pre-existing code. In the NavigatorState class add

List<_RouteEntry> getNavigationHistory(){
return _history;
}

And that should be all we need to do in the belly of the beast. We add this function so we can get the stack count in the history.

Now we want to get back to our “_willPopCallback” function. To set up for the logic in this callback function we will create 2 other functions one to keep a timer and one to show a toast.

bool isTimerRunning = false;

startTimeout([int milliseconds]) {
isTimerRunning = true;
var timer = new Timer.periodic(new Duration(seconds: 2), (time) {
isTimerRunning = false;
time.cancel();
});
}

void _showToast(BuildContext context) {
FlutterToast.showToast(
msg: "Press back again to exit",
toastLength: Toast.LENGTH_SHORT,
);
}

For Toast.LENGTH_SHORT the toast is visible for 2 seconds and ToastLENGTH_LONG it is visobile for 3.5 seconds so set the timer duration accordingly. Make sure to keep track of the timer state as well I did it using the isTimerRunning boolean.

Now we can dive into the callback function. Every time the back button is pressed the “_willPopCallback” will be triggered, what we want to do here is check if the current screen is the last screen in the stack and handle the situation accordingly.

Future<bool> _willPopCallback() async {

int stackCount =Navigator.of(context).getNavigationHistory().length;
if (stackCount == 1) {
if (!isTimerRunning) {
startTimeout();
_showToast(context);
return false;
} else
return true;
} else {
isTimerRunning = false;
return true;
}
}

we get the stack count by using the .length attribute of our getNavigationHistory() function. If this is the last stack we show the toast and if the back button is pressed while the toast is still visible we close the app, otherwise, we show the toast again.

The complete screen_holder.dart file should look something like this

Link to github repo : https://github.com/IMasuluke/FlutterExitPrompt

https://www.twitter.com/FlutterComm

--

--