Flutter remove specific route from route stack - flutter

I want to remove a specific route and stay on the same page without navigating to different page.
I have three pages PageA, PageB, PageC. I have the below code in PageC and removing PageB from Route stack. After removing it's navigating back to PageA (default route page). I want to stay on the RouteC without navigating.
final newRouteName = "/PageB";
navigatorKey.currentState!.popUntil((route) {
if (widget.routeSettings!.name == newRouteName) {
navigatorKey.currentState!.removeRoute(route);
}
return true;
});
Please help me, i stuck with this for days

I dont know if this works for you, but probably what you can do is:
When navigating from 'Page B' to 'Page C' make a
void _moveToPageC() {
Navigator.pushReplacementNamed(context, '/routeC');
}
That way, your stack would be page a > page c
Then if you want to go back to page a then you can simply pop page C
Hope, this helps

Related

Pop a screen in between in Flutter

I pushed three screens: ScreenOne > ScreenTwo(1) > ScreenTwo(2)
I'm at the second instance of ScreenTwo now, but I want to remove the first instance of ScreenTwo from the stack, so it should be ScreenOne > ScreenTwo(2).
When launching ScreenTwo(2) I know I shouldn't remove ScreenTwo(1) from the stack yet, so I can't just call Navigator.replace(). I really need to have ScreenOne > ScreenTwo(1) > ScreenTwo(2) for some time, and then remove the first instance of ScreenTwo(1).
How I can handle it? Navigator.pop() and similars only take into account the screen or screens on top of the stack.
If someone needs more context, this is for a phone app. Not an app for phones, but an app that mimics the behavior of a phone. So in reality, we have HomeScreen > CallScreen(Caller1) > CallScreen(Caller2). As the app can handle different calls at a time the first approach has been to map every call to a CallScreen and let every screen handle their own call events, so the first call can finish while the user is talking in the second one.
As discussed in this post:
How can I pop to specific screen in flutter
I quote:
If you didn't define any route in the MaterialApp then you need to define at the time of push.
Navigator.of(context).push(
MaterialPageRoute(builder: (_) {
return SecondPage();
},
settings: RouteSettings(name: 'SecondPage',),
));
You need to define the same route name
Navigator.of(context).popUntil((route){
return route.settings.name == 'SecondPage';
})
;
Or as an alternative if you did define the routes you can use that:
pushNamedAndRemoveUntil(
'/BottomNavigation', (Route<dynamic> route) => false);
In this case it is most suitable that you go from screen1 > Screen2 > replace previous with Screen3
Use this navigation from screen 2 to screen 3.
Navigator.pushReplacementNamed(context,"Third Screen");

Flutter - re-run previous page code after execution returns to it

I'm trying to figure out the best way to implement the proper navigation flow of a flutter app I'm building that involves a 3rd party authentication page (Azure AD B2C). Currently I have a page that serves simply as a "navigate to 3rd party auth login" page which is set as the initialRoute for my app. The first time through, it runs exactly the way I want it to, but I'm not able to figure out how to get that 'navigate to auth' page to re-run when navigated back to (after logout) so that the user ends up back at the 3rd party auth login page.
Basically what I'd like to do is, on logout - have the app navigate back to that page specified as the initialRoute page, and upon that page being navigated back to, have it re-launch the 3rd party auth login page just like it did the first time it executed.
I tried just awaiting the call to Navigator.push() and then calling setState((){}) afterwards, and that does re-display the page, but it just leaves that initial page sitting there, and doesn't end up triggering the execution the way it did the first time. initState() does not fire again, so neither does any of my code that's in there.
I've tried various methods off the Navigator object trying to reload the page or navigate to itself again, or just calling goToLogin() again after the await Navigator.push() call, nothing works.
Here's what I'm currently doing :
User launches the app, the initialRoute is LoginRedirect
class LoginRedirect extends StatefulWidget {
#override
_LoginRedirectState createState() => _LoginRedirectState();
}
class _LoginRedirectState extends State<LoginRedirect> {
#override
void initState() {
Utility.getConfig().then((value) {
config = value;
oauth = AadOAuth(config);
goToLogin(context);
});
super.initState();
}
void goToLogin(BuildContext context) async {
setState(() {
loading = true;
});
try {
await oauth.login(); // this launches the 3rd party auth screen which returns here after user signs in
String accessToken = await oauth.getAccessToken();
navigateToDashboard();
setState(() {
loading = false;
});
} on Exception catch (error) {
setState(() {
loading = false;
});
}
}
void navigateToDashboard() {
await navigator.push(context, MaterialPageRoute(builder: (BuildContext context) => Dashboard()));
// right here is where I'd like to call goToLogin() again after I Navigator.popUntil() back to this
// page, but if I try that I get an error page about how 'The specified child already
// has a parent. You must call removeView() on the child's parent first., java.lang
// .IllegalStateException and something about the bottom overflowed by 1063 pixels
}
}
After getting some config values and calling oauth.login() then I call a navigateToDashboard() method that pushes the Dashboard page on to the navigation stack.
Elsewhere in the code I have a logout button that ends up calling this code:
oauth.logout();
Navigator.popUntil(context, ModalRoute.withName('/LoginRedirect'));
which returns execution to where I called await Navigator.push() previously. But I can't figure out what I need to do there to have that LoginRedirect page execute again. I can't call goToLogin() again or it errors/crashes. I can't call initState() again, calling setState() doesn't do anything. I'm kinda stumped here, I thought this would be easy.
When logging out try: Navigator.pushReplacementNamed(context, "/LoginRedirect"); instead of Navigator.popUntil(context, ModalRoute.withName('/LoginRedirect'));

How can I go back to recent page of history with onPopPage in navigation 2.0

I'm practicing the new API, navigation 2.0, for my web project with flutter. I'm quite new to flutter either.
I successfully implemented the routing with navigation 2.0, but still can't figure out how the onPopPage works. If I tapped the button to navigate to the sub-page, the back button is automatically generated in the header. So when I clicked the back button in the header, it takes me home.
What if I implement another nested sub-page of the sub page, then I clicked the back button it takes me all the way to the top page, home.
I think it's because of the onPopPage function which I added like this. How can I edit this function to work properly. I want the back button to pop the only recent page of navigation history.
onPopPage: (route, result) {
if (!route.didPop(result)) {
return false;
}
_currentPath = 'home';
show404 = false;
notifyListeners();
return true;
},

Flutter GetX routing history

I it possible to see the navigator stack with GetX? I looked in the documentation but I could not find anything on this subject. I usually close for example dialogs like this
Get.until((route) => !Get.isDialogOpen);
But I was wondering if I could close routes if an instance of a specific page is in the routing history which would be something like this
Get.until((route) => !Get.routingHistory.contains('/someRoute'));
Note this isn't valid syntax.
You need to use:
Get.offUntil(page, (route) => false)
page means the new page to navigate.
(route) => false
Is the condition.
Get.until
Remove screens until satisfying the condition.
It’s the same with Navigation.popUntil().
You can use it like Get.until((route) => Get.currentRoute == '/home').
Get.offNamed
By the Named route, remove the current screen and add a new screen.
It’s the same with Navigation.pushReplacementNamed().
You can use it like Get.offNamed('/second').
Get.offAndToNamed
By the Named route, add a new screen and then, remove the previous screen.
It’s the same with Navigation.popAndPushNamed().
You can use it like Get.offAndToNamed('/second').
Get.offUntil
Remove screens until satisfying the condition, and then, add a new screen.
It’s the same with Navigation.pushAndRemoveUntil().
You can use it like Get.offUntil(page, (route) => (route as GetPageRoute).routeName == '/home').
Get.offNamedUntil
By the Named route, remove screens until satisfying the condition, and then, add a new screen.
It’s the same with Navigation.pushNamedAndRemoveUntil().
You can use it like Get.offNamedUntil(page, ModalRoute.withName('/home')).
Please use according to your usecase
GetX have another useful function:
int times = 2;
Get.close(times);
Close as many routes as defined by [times]
If you want to keep closing routes until you reach a page route....
Navigator.of(context).popUntil(ModalRoute.withName('/route-name'));
It is possible. Navigator.popUntil pops pages until a passed predicate returns true. We can query the following route in the navigator stack and decide what decision to make.
The GetX method for doing the same is
`
Get.offUntil( MaterialPageRoute(builder: (context) => const NewPage()), (route) {
var currentRoute = route.settings.name;
debugPrint("Get.currentRoute --- $currentRoute");
if(currentRoute == "/Home") {
return true;
} else {
return false;
}
}
`
The code above pops until home. Also, we can add custom logic in the if-else block above.
Get.until((route) {
if (route.settings.name == Routes.TEST1) {
//Return to the specified page
return true;
} else {
return false;
}
});
Get.offAll(Home()); // remove all previous routes and redirect to home
of with namedRoutes:
Get.offAllNamed('/home');

Flutter Navigation showing route as /

I have a card with PopupMenuButton that I can tap to perform the 'copy' action. I can also perform the same action from the card details page. The problem I have is to get back to the home page I have to cater for both paths. So if the action is performed from the details page, I need to pop twice to go back to the home page.
Action from the home page:
Home > add card page
navigator.pop() takes me back to home page
Action from the details page:
home > card details page > add card page
Having to pop twice here.
I know I have to do the pop atleast once and then I used the popUntil to check the current state of the route. For some reason, it is always popping twice.
After debugging, its showing current route as /
void _changeRoute(String newRouteName) {
bool isNewRoute = false;
// Pop once
Navigator.pop(context); // after this I should be on home page for the first path
Navigator.popUntil(context, (route) {
print('Current route is ${route.settings.name}');
if (route.settings.name == newRouteName) { // but this is showing current route as /
isNewRoute = true;
}
return true;
});
print('is home page: $isNewRoute');
if (!isNewRoute) {
Navigator.pop(context);
}
}
I have this working.
My problem was that in my Main App, I had specified the home property on MaterialApp. According to the documentation, if the home property is specified, it takes the route /. So my home page is / and I had it defined as /home in my routes and this was being overridden by /.