How to remove backstack including home page in flutter - flutter

I have seen many examples but none of them providing me a way to remove the entire back stack(including the home page) while navigating to the next page.
Eg: I have a few login pages once a user successfully entered login credentials user move to the home screen, so here I want to remove all previous screen which appeared till now, How can I do that?
Currently using code:
Navigator.of(context).pushNamedAndRemoveUntil(
HomeScreen.route_name, ModalRoute.withName('/'));

To remove all the routes below the pushed route, use a RoutePredicate that always returns false (e.g. (Route route) => false).
So for your code to work as expected, remove ModalRoute.withName('/') and give a route predicate which returns false. So it should be
Navigator.of(context).pushNamedAndRemoveUntil(
HomeScreen.route_name, (Route<dynamic> route)=>false);
For reference see the official documentation

Try this out. This code push the given route onto the navigator and then remove all the previous routes even HomeScreen.
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(
builder: (BuildContext context) => HomeScreen(),
),
(route) => false,
);
Note: This is tested on my project. So I hope it will 100% work

Try this way
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(builder: (dialogContex) => HomePageScreen()),
ModalRoute.withName("/HomePageScreen"));

or with Getx:
Get.offNamedUntil('home', (route) => false);

Related

ModalRoute.withName never returns true in pushNamedAndRemoveUntil

I have been wrestling with this issue for a couple of days now and I haven't been able to find a solution, hence the post.
At one point in my app, I need to pop 2 routes from the navigator stack and push a new route. After researching the best way to do this, I have found that using pushNamedAndRemoveUntil is the best way, as I can specify ModalRoute.withName('/<route_name>') and it will pop the routes until it reaches /<route_name> at which point it will stop and push the new route. This is the line I have been using Navigator.of(context).pushNamedAndRemoveUntil('/raceadmin_reporting', ModalRoute.withName('/raceadmin_page'));.
My issue though is that it doesn't work for me. It doesn't seem to matter what I put in /<route_name>, pushNamedAndRemoveUntil pops all the routes, which leads me to believe that ModalRoute.withName never returns true.
I have also tried Navigator.of(context).pushNamedAndRemoveUntil('/raceadmin_reporting', (route) => route == RaceAdminPage.route()); and it doesn't work either.
When I look at the debugger, this is what I see:
App Navigator Stack
The route I am trying to pop until is the RaceAdmin page, which is clearly in the stack. In the definition of that class, I added the line static const routeName = '/raceadmin_page'; which is what I call in ModalRoute.withName('/raceadmin_name') and it doesn't work.
My routes are defined in the routes.dart file as per below:
static Route<dynamic> generateRoute(RouteSettings settings) {
switch (settings.name) {
case '/':
return MaterialPageRoute(builder: (context) => RailMeatApp());
case '/raceadmin_page':
return MaterialPageRoute(builder: (context) => const RaceAdminPage());
case '/raceadmin_pendinglist':
return MaterialPageRoute(builder: (context) => PendingResultsList());
case '/raceadmin_pendingresults':
final args = settings.arguments as Map<String?, String?>;
return MaterialPageRoute(
builder: (context) => PendingResultsPage(
raceId: args['raceId'] as String,
));
case '/raceadmin_reporting':
return MaterialPageRoute(builder: (context) => RaceAdminReporting());
default:
return _errorRoute();
}
}
And my MaterialApp is defined as per below:
return MaterialApp(
navigatorKey: _navigatorKey,
home: _railmeatHome(),
onGenerateRoute: RailmeatRoutes.generateRoute,
);
}
In the Flutter debugger, I can look at the MaterialApp widget and I can see in its state that the navigator has 4 entries in its _history property as shown below:
MaterialApp Widget Properties
If I click on any of the entries in the _history, I see the the same info as below:
Route property in _history
As you can see, the name property under _settings is null, which, in my mind, would explain why ModalRoute.withName can't find the right route, but I am not sure that my thinking is accurate.
What should I do differently to make pushNamedAndRemoveUntil work?
Thanks a lot in advance,
Bertrand.
Try this instead
Navigator.of(context)
.pushNamedAndRemoveUntil('/routename', (Route<dynamic> route) => false);
Or
Navigator.of(context).popUntil(ModalRoute.withName('/root'));

How to pop 2 screen at once in flutter

I have not created any routes to navigate between screens. I use Navigator to navigate:
Navigator.push(context, MaterialPageRoute(builder: (context) => HomePage()));
what I have done is navigate to four screens from homePage to success screen:
HomePage => CreatePostScreen => CreateImagePost => SuccessfulScreen
when I reach to successfulscreen I would like to pop two screens and get back to CreatePostScreen.
I do not want to write Navigator.pop(context) two times.
I tried to use this, but it will come up with a black screen:
Navigator.popUntil(context, (route) => route is CreatePostScreen);
but this is not working. I would like to learn how flutter handles widget navigation not by route names and solution to this.
I know something about how navigator class handles with route name but I would like to know how to solve it if I push widgets and its working.
What you're trying to do :
Navigator.popUntil(context, (route) => route is CreatePostScreen);
Doesn't work because route is of type Route, not a widget. This leads to all the routes being popped since no Route satisfies your predicate.
What you should do is push your route with a setting, e.g. :
Navigator.push(context, MaterialPageRoute(builder: (context) => HomePage(), settings: RouteSettings(name: "/home")));
And then use that in your predicate. E.g. :
Navigator.popUntil(context, (route) => route.settings.name == "/home");
Hope this will help you. You can use popUntil method of Navigation Class.
int count = 0;
Navigator.of(context).popUntil((_) => count++ >= 2);
You would try with the below code:
onPressed: () async {int count = 0; Navigator.of(context).popUtil((_)=> count++>= 2);}
The code you would refer from is that, you would implement the logic to let the system indicate whether pop continues if it returns false it will keep popping until it the logic returns true
void popUntil(bool Function(Route<dynamic>) predicate)
If you want to pop two screens you can use cascade operator like this:
Navigator.of(context)..pop()..pop();

How can I pop all routes and push a new one popUntil() if it had not been called

I am using this code Navigator.popUntil(context, ModalRoute.withName('/login')) to pop all my routes till i get to the particular page registered under the route '/login'. My screen goes blank when the route '/login' is never called and I use Navigator.popUntil(context, ModalRoute.withName('/login')).
How can I achieve a situation where even if I had not called Navigator.pushNamed(context, '/login') all the routes will be popped and 'login' will be pushed and called.
What you're looking for is pushNamedAndRemoveUntil method:
Push the route with the given name onto the navigator that most
tightly encloses the given context, and then remove all the previous
routes until the predicate returns true.
You need to use a RoutePredicate that always returns false to remove all the previous routes:
(Route<dynamic> route) => false
Here is an example:
Navigator.pushNamedAndRemoveUntil(
context,
'/login',
(Route<dynamic> route) => false,
);

Flutter back-pressed shows black screen

I have created NavigationDrawer in flutter before navigation drawer screen appear to user I have 3 screen before it
splash screen
intro slider
Login screen
NavigationDrawer
I want to close my app when user press back button in android phone from navigationdrawer screen but it will shows black screen.
I have called below called for navigation from login to drawer
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(
builder: (BuildContext context) => NavigationDrawerDemo(),
),
ModalRoute.withName('/LoginFieldForm'));
I called loginfieldform with
Navigator.push(context,
new MaterialPageRoute(builder: (context) =>new LoginFieldForm()));
I think you have pushed the "LoginFieldForm" with the Navigator.push method and trying to remove it using the named routes.
For Ex :
// Puching a route with Navigator.push method
Navigator.push(
context,
MaterialPageRoute(builder: (context) => LoginFieldForm()),
);
// Removing using the named routes.
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(
builder: (BuildContext context) => NavigationDrawerDemo(),
),
ModalRoute.withName('/LoginFieldForm'));
You can only use ModalRoute.withName() if you have added the route using named routes.
Your route probably has not a name set. If so, popping until the name is matched will result in popping everything, since the name you're looking for will never be found.
When you push LoginFieldForm ensure to pass a settings to the Route.
When pushing, you can do this:
MaterialPageRoute(
settings: RouteSettings(name: "routeName"),
builder: (context) => YourWidget(),
)
If you're within onGenerateRoute you already have settings passed as an argument to the onGenerateRoute function. In that case, just forward them to the MaterialPageRoute:
MaterialPageRoute(
settings: settings, //these settings are arguments from the function
builder: (context) => YourWidget(),
)
To close the app you may use exit(0) of dart:io on back press.exit(0) help out to Exit the Dart VM process immediately with the given exit code.
This does not wait for any asynchronous operations to terminate. You may find more information about exit(0) here
Or
SystemChannels.platform.invokeMethod('SystemNavigator.pop');
For more detail you may check here
Use-case: pushNamedAndRemoveUntil
Navigator.of(context).pushNamedAndRemoveUntil('/LoginFieldForm',
(Route<dynamic> route) => false);

Flutter: Move to a new screen without providing navigate back to previous screen

I'm implementing an authentication flow in my Flutter app.
After a sign in attempt, the CheckAuth (which checks whether a user is signed in or not and then opens home screen or sign up screen accordingly) is opened with this code:
void _signIn() async {
await _auth
.signInWithEmailAndPassword(
email: _userEmail.trim(), password: _userPassword.trim())
.then((task) {
// go to home screen
if (task.getIdToken() != null) {
setState(() {
Navigator.pushReplacement(
context,
new MaterialPageRoute(
builder: (BuildContext context) => new CheckAuth()));
});
} else {
print("Authentication failed");
}
});
}
Problem: I can successfully sign in to the app, but if I tap back button after I sign in, it goes back to the sign in screen (while I expect it to exit from the app).
Question: How to move from one screen to another in Flutter without the way back?
Do I need to somehow delete the navigator history? Or don't use navigator at all? I tried Navigator.replace method, but it didn't seem to work.
You need to use Navigator.pushReplacement when leaving the auth screen too. Not just when redirecting to login page.
You can use the pushAndRemoveUntil method:
Push the given route onto the navigator that most tightly encloses the given context, and then remove all the previous routes until the predicate returns true. To remove all the routes below the pushed route, use a [RoutePredicate] that always returns false (e.g. (Route<dynamic> route) => false).
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(builder: (context) => MainPage()),
(Route<dynamic> route) => false,
);
You need to use
Navigator
.of(_context)
.pushReplacement(new MaterialPageRoute(builder: (BuildContext context) => page));
Where _context is object of BuildContext
And page is which page you directed to.
I think you probably have already solved this. But you can set "automaticallyLeadingImplied: false" in the AppBar of the Scaffold you are navigating to.
Just simply add the below code:
Navigator.of(context).pushNamedAndRemoveUntil('/routeName', (route) => false);
We can use routes for the same
Like:
routes: {
LoginScreen.route_name: (_) => LoginScreen(),
.....
},
And use below code whenever you want to push and remove the backstack
Navigator.of(context).pushReplacementNamed(LoginScreen.route_name);
Note: Define static String inside widget LoginScreen
I have resolved this by popping from current page and showing new page:
Navigator.pop(context);
Navigator.of(context).pushReplacement(MaterialPageRoute(builder: (context) => newPage));
Here is the solution -
Use pushAndRemoveUntil instead of pushReplacement
Also, can be use maintainState: true
For set root page
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(
builder: (context) => pageName, maintainState: true),
(Route<dynamic> route) => false);
For Push Page one page to another
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => pageName,
maintainState: false),)
**If you want to refresh always while appearing page then use: **
maintainState: false
For anyone wondering there is a new argument that needs to be returned false Navigator.of(context).pushNamedAndRemoveUntil('/', (route) => false);
Navigator.of(context, rootNavigator: true).pop();
Navigator.pushNamed(context, '/');
It was not working for me because I was using the home proptery rather than initialRoute on the MaterialApp.
This is a link where there's the folloing warning which helped me to spot the error: https://docs.flutter.dev/cookbook/navigation/named-routes#2-define-the-routes
Warning: When using initialRoute, don’t define a home property.
if you are working with Getx state managemaent then you can try this
Get.of(()=> NewPage());