Issue
For example, I have this navigation stack:
- <Some kind of top level screen>
- Create avatar
- Step 1
- Step 2
- Step 3
- ... Step n ...
- Verify result
On verify result, if it’s success, I want to change the stack into this:
- <Some kind of top level screen>
- Success
So that if the user taps on the Android physical back button, it will immediately return to <Some kind of top level screen>
, instead of Verify result
screen, and doesn’t matter how deep the navigation stack is.
How can I do this? The way I usually do is:
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(builder: (context) => Success()),
(Route<dynamic> route) => false,
);
But this causes the Navigation stack to be:
- Success
If the user tap on Android physical back button, the app will be closed instead of returning to <Some kind of top level screen>
. What I want is to pop all the stack until just before the <Some kind of top level screen>
(which it can be various kind of screen that I cannot predict), and then push the Success screen on top of it.
There’s actually a button in the Success
screen that bring user to <Some kind of top level screen>
, but I just learned that some user actually choose to tap on the Android physical back button instead of the big blue button I presented on the screen. To block back button on this screen feels like a wrong design / bad practice.
Solution
Instead of always returning false
in the predicate, do something like
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(builder: (context) => Success()),
(Route<dynamic> route) => route != <Some kind of top level screen>,
);
Then the popping of route will spare you top level screen.
If you are using named route, the predicate could be
ModalRoute.withName('<Some kind of top level screen>')
More detail can be found RTFM
Answered By – Ber
Answer Checked By – Mary Flores (FlutterFixes Volunteer)