Flutter: How to pop last visited screen from stack in flutter - flutter

Let say i have three screens: wallet, payments, add card. I want to pop payments screen from stack when i'm on add card screen and navigate it to wallet screen without using navigator.push on click on icon plus the back icon of device.
here is the flow of screen:
wallet screen has a button which navigate to the payments screen, then payments screen has a button which navigate to the add card screen . So, now i want when i am on add card screen and click on back icon of android or the icon which is on add card screen both should navigate to wallet screen.
Please help how to do this.

It's not very clear from your question how your navigation stack should look: Is payments first in the stack, and can you go from there to add card and wallet? Or should only one exist?
I think you can use pushReplacement: https://api.flutter.dev/flutter/widgets/Navigator/pushReplacement.html
That way, it'll automatically replace the current route with the new one, and your back button will simply close the app (or go back to the screen before it). If you want some custom behavior when the back button is pressed, you can always use a WillPopScope: https://api.flutter.dev/flutter/widgets/WillPopScope-class.html

Navigator.removeRoute(context, MaterialPageRoute(builder: (context) => payments()));
use this code when you remove your payments screen

Please try this below code
PopAndPushNamed ->
Pop the current route off the navigator that most tightly encloses the given context and push a named route in its place.
It pops payments screen from the navigation stack and only wallet screen remains in Navigation stack
Navigator.popAndPushNamed(context, '/addCard');
PushNamedAndRemoveUntil ->
It pushes the route with the given name (Wallets) onto the navigator, and then remove all the previous routes until the predicate returns true. Here it is using a RoutePredicate that always returns false (Route route) => false. In this situation it removes all of the routes except for the wallets route pushed.
//named
Navigator.of(context)
.pushNamedAndRemoveUntil('\wallets', (Route<dynamic> route) => false);
//not named
Navigator.of(context).pushAndRemoveUntil(MaterialPageRoute(builder: (context) =>
Wallets()), (Route<dynamic> route) => false),
PopUntil ->
Calls pop repeatedly on the navigator that most tightly encloses the given context until the predicate returns true.
The predicate may be applied to the same route more than once if Route.willHandlePopInternally is true.
To pop until a route with a certain name, use the RoutePredicate returned from ModalRoute.withName.
Navigator.popUntil(context, ModalRoute.withName('/wallets'));

try this:
Navigator.pushReplacement()

Related

How to enable back button in a screen after using Navigator.pushReplacementNamed() to replace the page in flutter?

Let's say I have two screens A and B .
I am on screen A and I use pushReplacementNamed() to get to screen B.
Now I want to go back to screen A when user swipes right (default in iOS for back button).
Screen A :
Navigator.pushReplacementNamed(context, '/B'),
Screen B :
WillPopScope(
onWillPop: () async {
Navigator.pushReplacementNamed(context, '/A');
return false;
}),
But this is not working. Back button is still disabled.
Note - I don't want to make custom back button in AppBar to achieve this. I want to use the default back button behaviour.
What I think is wrong with your code is that you're returning false from onWillPop, return false disregards the action of the back tap. Try changing that to true.
Also if you want to eventually go back to screen A from screen B it makes more sense to just use a push() on screen A and then on screen B inside onWillPop you no longer need to manually pop the route using navigator, you can just return true.
Update
In response to the your comment below, for what you want to achieve, you can normally push a route when on Home page and then on other pages you could just use pushNamedAndRemoveUntil:
Navigator.of(context).pushAndRemoveUntil("B",ModalRoute.withName('Home'));
It will push the page you want and remove everything until page Home. Since "Home" will now always be the root, you no longer need to override onWillPop and can proceed with a normal pop on back button.
Note: Page "Home" has to already be present in the stack for this to work.
If you want to push and remove everything else from the stack change:
ModelRoute.withName("Home"),
To
(Route<dynamic> route) => false,

Flutter navigation pop from which screen

Is there anyway to check route name of last screen after pop? When application start and land on home screen, there are several widgets like view profile, product carousel and so on.
Scenario: User navigate into product listing page, then detail page, click purchase and perform actions. After user purchased, shows purchased successful screen, call Navigator.of(context).popUntil(routeName) back to home screen.
What I want to achieve: After land in home screen, programmatically call api to refresh my balance. Route Observer able to detect navigation back to home screen with didPopNext() method. But this is called no matter it pop from which screen. Therefore the api will repeatedly called which is not ideal. How do I know it was pop from purchased successful screen instead of product listing screen?
Grateful on any helps and hints!
If you where using pop() then you have an option to return some data to previous route but since you are using popUntil() you won't be able to do this. So I think you should clear every route and push home route again from purchased successful page using either pushAndRemoveUntil() or pushNamedAndRemoveUntil(). That means you can now pass an argument to home screen by which you can decide whether to call the API or not.
Navigator.of(context).pushNamedAndRemoveUntil(
'/',
(Route<dynamic> route) => false,
arguments: []
);
Another option would be to figure out a way to return data using popUntil(), Something like this, maybe?

How to clear the navigation stack in Flutter

I want my application to a have Welcome screen, with registration and login option. When I tap on "registration" button to navigate to my Registration screen, i use:
Navigator.push
When I press the "back" button within the Registration screen, it must return to the Welcome page.
But after the user completes the registration I'm using the following code in the Homepage to navigate to my home.
Navigator.pushReplacement
The problem is, when I pressed the "back" button, my app is coming back to the Welcome screen, instead of staying within the Home.
Any idea what is going on?
You can use the following method to clear the navigation stack when you navigate:
Navigator.of(ctx).pushAndRemoveUntil(YourRoute, (Route<dynamic> route) => false);
The second parameter is a Predicate to decide weather the route will be deleted from the stack or not.
Using this method, you'll clear the whole stack before navigating to the route, that way, you won't be able to go back to your Welcome page.

Navigating in and outside CupertinoTabBar View

this is my first app in Flutter, everything was fine and smooth util now that I´m geeting a little bit blocked.
I cannot navigate between a CupertinoTabBar and my Login display (that shouldn´t have one) the way I show you on the image.
Login works fine and when receives a 200 response from server, navigates to the view with the CupertinoTabBar.
But when I press on the LogOut button, I´d need to comeback to the loginView, without any tabBar.
The only way I´ve been able to navigate back to login is like that:
Navigator.push(context, CupertinoPageRoute(builder: (context) => LoginView()),);
And that keeps my LoginView inside the tabBar in the widgets stack, and what is worse, if I logIn again I endup stacking another tabBar over the previous one.
What could be a better approach for that?
Many Thanks,
Gabi
You can use pushAndRemoveUntil to pop routes that you don't need in stack. Probably, you want to remove all the routes like that:
Navigator.of(context).pushAndRemoveUntil(CupertinoPageRoute(builder: (context) => LoginView()), (r) => false);
or, if your current route is logout, you can replace it with login route and route stack will remain the same:
Navigator.of(context).pushReplacement(CupertinoPageRoute(builder: (context) => LoginView()));

Flutter launch new independent screen

I am having trouble launching new screen widget. I have main.dart where I am using bottomNavigationBar and body for ViewPager UI. Now I have 3 bottom tabs and when I go to 2nd tab's view and click on a button to launch another screen/view using:
onTap: () => Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => ViewMyContactList(),
),
)
the new screen replaces the 2nd tab's view, when I go to 3rd tab then come back to 2nd tab, the new screen is gone and 2nd tab's initial screen is back. Also when new screen replaces the 2nd screen's initial view and when I do system back press in Android, the app exits straightaway.
You are trying to do Multiple Navigators with BottomNavigationBar
You can reference this doc for detail https://medium.com/coding-with-flutter/flutter-case-study-multiple-navigators-with-bottomnavigationbar-90eb6caa6dbf
Each tab must keep it'own Page Route, you can use the demo code in doc or
You can use the following two package to help you
https://pub.dev/packages/multi_navigator_bottom_bar
Helps you to build multi-navigator bottom navigation bar more easily.
https://pub.dev/packages/nested_navigators Flutter widget for implementing multiple nested navigators with their own route stacks.