Reputation: 12031
I want to develop a logout button that will send me to the log in route and remove all other routes from the Navigator
. The documentation doesn't seem to explain how to make a RoutePredicate
or have any sort of removeAll function.
Upvotes: 235
Views: 253804
Reputation: 2676
I can do that using the following code snippet :
Navigator.of(context).pushAndRemoveUntil(
MaterialPageRoute(
builder: (context) => LoginScreen(),
),
(Route<dynamic> route) => false,
);
if you want to remove all the route below the pushed route, RoutePredicate always return false, e.g (Route route) => false.
Upvotes: 189
Reputation: 61
Using GetX makes it easier.
Get.offAll( ()=> Loginpage() ) //will remove all previous routes and navigate you to login page Get.offNamed('/login_page') //does the same thing.
Upvotes: 0
Reputation: 1650
First see chrislondon answer, and then know that you can also do this --> If you do not have access to the (context).
navigatorKey.currentState.pushNamedAndRemoveUntil('/login', (Route<dynamic> route) => false);
Upvotes: 3
Reputation: 7012
Newer Flutter version seem to replace
(Route<dynamic> route) => false);
by
ModalRoute.withName('/'));
Upvotes: 1
Reputation: 370
If you are using namedRoutes,
This statement removes all the routes in the stack and makes the pushed one the root.
then you can do this by simply :
Navigator.pushNamedAndRemoveUntil(context, "/login", (Route<dynamic> route) => false);
Where "/login" is the route you want to push on the route stack.
Upvotes: 20
Reputation: 63
Use this, it worked perfectly for me:
Navigator.pushNamedAndRemoveUntil(
context, '/loginscreen', (Route<dynamic> route) => false);
Make sure you add the last line, parameter, and you're good to go.
Upvotes: 5
Reputation: 937
use popUntil like following
Navigator.popUntil(context, (route) => route.isFirst);
Upvotes: 21
Reputation: 10879
In my case I had this painting Page 1 (Main) -> Page 2 -> Page 3 -> Page 4.
When I had to go to Page 4, the Page 2 and Page 3 going back did not have to appear, but I had to go to Page 1 again. At this point going to Page 4 I did:
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(
builder: (BuildContext context) =>
Workout()),
(Route<dynamic> route) => route.isFirst);
The instructions are: go to page 4 (Workout) and remove all previous pages up to 1, that is (Main).
In your case that can be to switch from anything to a Login, then:
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(
builder: (BuildContext context) =>
Login()),
(Route<dynamic> route) => false);
That is, go to Login and remove all previous pages, because there is a false.
Upvotes: 9
Reputation: 329
In my case this solution works:
Navigator.pushNamedAndRemoveUntil(" The Route you want to go to " , (Route route) => false);
Upvotes: 7
Reputation: 20221
I don't know why no one mentioned the solution using SchedularBindingInstance, A little late to the party though, I think this would be the right way to do it originally answered here
SchedulerBinding.instance.addPostFrameCallback((_) async {
Navigator.of(context).pushNamedAndRemoveUntil(
'/login',
(Route<dynamic> route) => false);
});
The above code removes all the routes and naviagtes to '/login' this also make sures that all the frames are rendered before navigating to new route by scheduling a callback
Upvotes: 11
Reputation: 381
Another solution is to use pushAndRemoveUntil()
. To remove all other routes use ModalRoute.withName('/')
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(builder: (BuildContext context) => Login()),
ModalRoute.withName('/')
);
Reference: https://api.flutter.dev/flutter/widgets/NavigatorState/pushAndRemoveUntil.html
Upvotes: 38
Reputation: 641
to clear route -
onTap: () {
//todo to clear route -
Navigator.of(context).pop();
Navigator.push(context, MaterialPageRoute(builder: (context) => UpdateEmployeeUpdateDateActivity(_token),));
widget.listener.onEmployeeDateClick(_day,_month, _year);
}
Upvotes: 2
Reputation: 79
Not sure if I'm doing this right
but this suits my use-case of popping until by root widget
void popUntilRoot({Object result}) {
if (Navigator.of(context).canPop()) {
pop();
popUntilRoot();
}
}
Upvotes: 7
Reputation: 687
This is working for me. Actually, I was working with bloc but my issue was login screen bloc. It was not updating after logout. It was holding the previous model data. Even, I entered the wrong entry It was going to Home Screen.
Step 1:
Navigator.of(context).pushNamedAndRemoveUntil(
UIData.initialRoute, (Route<dynamic> route) => false);
where,
UIData.initialRoute = "/" or "/login"
Step 2:
It's working to refresh the screen. If you are working with Bloc then It will very helpful.
runApp(MyApp());
where,
MyApp() is the root class.
Root class (i.e. MyApp) code
class MyApp extends StatelessWidget {
final materialApp = Provider(
child: MaterialApp(
title: UIData.appName,
theme: ThemeData(accentColor: UIColor().getAppbarColor(),
fontFamily: UIData.quickFont,
),
debugShowCheckedModeBanner: false,
//home: SplashScreen(),
initialRoute: UIData.initialRoute,
routes: {
UIData.initialRoute: (context) => SplashScreen(),
UIData.loginRoute: (context) => LoginScreen(),
UIData.homeRoute: (context) => HomeScreen(),
},
onUnknownRoute: (RouteSettings rs) => new MaterialPageRoute(
builder: (context) => new NotFoundPage(
appTitle: UIData.coming_soon,
icon: FontAwesomeIcons.solidSmile,
title: UIData.coming_soon,
message: "Under Development",
iconColor: Colors.green,
)
)));
@override
Widget build(BuildContext context) {
return materialApp;
}
}
void main() => runApp(MyApp());
Here is My Logout method,
void logout() async {
SharedPreferences preferences = await SharedPreferences.getInstance();
preferences.clear();
// TODO: we can use UIData.loginRoute instead of UIData.initialRoute
Navigator.of(context).pushNamedAndRemoveUntil(
UIData.initialRoute, (Route<dynamic> route) => false);
//TODO: It's working as refresh the screen
runApp(MyApp());
}
Upvotes: 6
Reputation: 761
In case you want to go back to the particular screen and you don't use named router can use the next approach
Example:
Navigator.pushAndRemoveUntil(context,
MaterialPageRoute(builder: (BuildContext context) => SingleShowPage()),
(Route<dynamic> route) => route is HomePage
);
With route is HomePage you check the name of your widget.
Upvotes: 26
Reputation: 774
Another alternative is popUntil()
Navigator.of(context).popUntil(ModalRoute.withName('/root'));
This will pop all routes off until you are back at the named route.
Upvotes: 55
Reputation: 12031
I was able to accomplish this with the following code:
Navigator.of(context)
.pushNamedAndRemoveUntil('/login', (Route<dynamic> route) => false);
The secret here is using a RoutePredicate that always returns false (Route<dynamic> route) => false
. In this situation it removes all of the routes except for the new /login
route I pushed.
Upvotes: 498