Flutter Navigation pop to index 1
Asked Answered
N

12

138

I am recursively adding routes to the navigator. There could be 20 views or more. Pop works as advertised, but I would like to pop to index 1 and remove all push history. is there a way to replace this pop command with something like... returntoIndex0...

      new ListTile(
        title: new RaisedButton(
          child: new Text("POP"),
          onPressed: () {
            var route = new MaterialPageRoute(
              builder: (BuildContext context) =>
                  new NextPage3(value:"hi there from 3"),
            );
            Navigator.pop(context);
          },
        ),
      ),
Nacred answered 5/4, 2018 at 12:42 Comment(0)
H
328

If you do not use named routes, you can use

Navigator.of(context).popUntil((route) => route.isFirst);
Haun answered 21/2, 2019 at 8:23 Comment(6)
Navigator.popUntil(context, (Route<dynamic> route) => route.isFirst); This is also working fine for me.Waterfall
For some reason, when using .push.then(), when I use .popUntil((route) => route.isFirst;) it won't resolve the .then.Germano
Thanks mate. There were nowhere to find how to popUntil without name routesBoigie
This is the answer I've been searching for! Thanks!Siddra
can please someone explain what will popUntil((route) => route.isFirst) do? As i am using to pop all backstack till home widget, but it also pop the home widget from backstack.Doorstone
this approach is perfect!Unexacting
D
123

In case you know exactly how many pops should be performed:

For example for 2 pops:

count = 0;
Navigator.popUntil(context, (route) {
    return count++ == 2;
});
Danged answered 29/9, 2019 at 20:35 Comment(3)
Slight variation as its hard to track number of pops at least in our app. I have used: Navigator.popUntil(context, (route) => route.isFirst); It worked perfectly.Brand
pop gets better UX, it is much faster than push.Orontes
I know this but UI is disturbed because we are popping to Two screens at once. I think there must be some seconds of delay. What do u say?????Hymie
V
72

If you are using MaterialPageRoute to create routes, you can use this command:

Navigator.popUntil(context, ModalRoute.withName(Navigator.defaultRouteName))

Navigator.defaultRouteName reflects the route that the application was started with. Here is the piece of code that illustrates it in more detail:

child: InkWell(
          child: Row(
            mainAxisAlignment: MainAxisAlignment.spaceEvenly,
            children: <Widget>[
              Image(
                image: AssetImage('assets/img/ic_reset.png'),),
              Text('Change my surgery details',
                style: TextStyle(color: Colors.blue, decoration: TextDecoration.underline),),
            ],
          ),
          onTap: () =>
              Navigator.popUntil(context, ModalRoute.withName(Navigator.defaultRouteName))
        ),

Hope this helps.

Vevine answered 27/7, 2018 at 16:43 Comment(0)
L
31

For me I used this when pushing a new page:

widget = MyWidget();
Route route = CupertinoPageRoute(builder: (context) => widget, settings:RouteSettings(name: widget.toStringShort()));
Navigator.push(context, route);

Then to go back to specific page:

Navigator.of(context).popUntil((route) => route.settings.name == "MyWidget");
Linolinocut answered 3/6, 2019 at 21:19 Comment(1)
Great! Working nicely!Hydrogenous
E
26

Use popUntil method as mentioned in the docs

Typical usage is as follows:

Navigator.popUntil(context, ModalRoute.withName('/login'));

Enzyme answered 5/4, 2018 at 13:58 Comment(4)
I'll experiment more, but my issue is that I am building dynamically. I add NextPage on the fly.... if the DB calls for it. I was looking for a way that would just destroy the Navigation History and just rest for /. I read the Docs and saw the PopUntil. just wanted some ideas.Nacred
I have a situation. I have Screen1 and Screen2. I navigate from Screen1 to Screen2. Now what I want is that when I back press from Screen2. The app should finish.Isabelleisac
@AnkitShukla Navigator.of(context) .pushNamedAndRemoveUntil('/2ndScreen', (Route r) => r == null);Enzyme
please have a look https://mcmap.net/q/168232/-flutter-navigationRuling
P
17

Here Dashboard() is the screen name. So this will pop out all the screens and goto Dashboard() screen.

Navigator.of(context).pushAndRemoveUntil(
                  MaterialPageRoute(builder: (c) => Dashboard()),
                  (route) => false)
Poock answered 27/8, 2020 at 11:43 Comment(6)
It pops out all screens until reaches "Dashboard screen" but it also forgets all previously visited screens before "Dashboard screen" which is very weird part of it. Any suggestion to keep remember previous pages of "Dashboard screen". eg. If user comes on Dashboard from Home screen then do something on next screens (eg. update profile screen) of dashboard. If user is redirected from "update profile screen" to "Dashboard" then "Dashboard screen" should forget "update profile screen" but remember "Home screen". Back button should always display in all cases on "Dashboard screen". How can we do?Colt
there is no way to keep store all the middle screen during popping out the screens.Poock
Screens flow is as: 1) Home Screen -> 2) Dashboard Screen -> 3) Update Profile ScreenColt
When user submits "Update Profile Screen" then It should be redirected to Dashboard screen and forgotton "Update Profile Screen". Dashboard screen should always have back button and when user taps on back button of Dashboard screen, it should be redirect to Home Screen. Now tell me which "Navigator.of(context).XXXXX" function will be used for the same. Thanks.Colt
it is very simple just call Navigator.of(context).pop() after submit the "Update Profile Screen". it will goes to 2) Dashboard screen. and the back button in Dashboard screen will redicrect you to the 1) Home screen.Poock
But "Navigator.of(context).pop()" will NOT show snackbar message on "Dashboard Screen" which was set on "Update Profile Screen". Any other suggestion. Thanks for your reply.Colt
A
8

You can also do it like this

Navigator.of(context)
            .pushNamedAndRemoveUntil('/Destination', ModalRoute.withName('/poptillhere'),arguments: if you have any);

The use case is to go the desired screen and pop the screens in between as you require.

For more info, you can check this Post Explaining other Solutions

Additory answered 13/6, 2020 at 4:35 Comment(0)
T
2

I tried other answers in this post, and somehow they causing the following exception.

To safely refer to a widget's ancestor in its dispose() method, save a reference to the ancestor by calling dependOnInheritedWidgetOfExactType() in the widget's didChangeDependencies() method.

The relevant error-causing widget was
    MaterialApp 
lib/main.dart:72
When the exception was thrown, this was the stack
#0      Element._debugCheckStateIsActiveForAncestorLookup.<anonymous closure> 
package:flutter/…/widgets/framework.dart:3781
#1      Element._debugCheckStateIsActiveForAncestorLookup 
package:flutter/…/widgets/framework.dart:3795
#2      Element.dependOnInheritedWidgetOfExactType 
package:flutter/…/widgets/framework.dart:3837
#3      Theme.of 
package:flutter/…/material/theme.dart:128
#4      XXxxXX.build.<anonymous closure> 
package:xxx/widgets/xxx.dart:33
...
════════════════════════════════════════════════════════════════════════════════

The following answer fixed the issue. https://mcmap.net/q/168233/-how-to-reset-the-base-route-in-my-flutter-app-that-is-pop-any-routes-and-replace-it-with-a-new-one-using-navigator

Navigator.pushNamedAndRemoveUntil(context, '/', (_) => false);
Tubercle answered 29/6, 2020 at 10:26 Comment(0)
N
1
//========================================================
          new ListTile(
            title: new RaisedButton(
              child: new Text("POP until"),
              onPressed: () {
                var route = new MaterialPageRoute(
                  builder: (BuildContext context) =>
                      new NextPage3(value:"hi there from 3"),
                );
               //Navigator.pop(context, ModalRoute.withName('/'));
                Navigator.popUntil(context,ModalRoute.withName('/'));                
              },
            ),
          ),
//========================================================

replace .pop with .popUntil, actually works very elegantly.

Nacred answered 6/4, 2018 at 10:43 Comment(0)
S
1

This always gets me the expected result. And will pop to route of current Navigator stack

 Navigator.of(context, rootNavigator: true).pop();
Starwort answered 9/3, 2021 at 12:18 Comment(0)
Q
1

This will pop all the routes until the main default route and push to your destination route.

Navigator.pushNamedAndRemoveUntil(context, "destination_route", ModalRoute.withName('/')); 
Queer answered 24/1, 2022 at 21:14 Comment(0)
I
1

Example for two pops, using cascade operator:

Navigator.of(context)..pop()..pop();

Irrigation answered 4/11, 2022 at 11:48 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.