7

Below is the code.

  1. Navigation to Login page, from Home page
    ElevatedButton(
              onPressed: () => Navigator.of(context, rootNavigator: true)
                  .push(MaterialPageRoute(
                fullscreenDialog: true,
                builder: (context) => UserLoginPage(),
              )),
              child: Text('Login to continue'),
            ),

Inside Login page:

BlocConsumer<UserAuthCubit, UserAuthState>(
            listener: (context, state) {
              if (state is UserAuthorized) {
                Navigator.of(context, rootNavigator: true).pop();
              }
              if (state is UserAuthWaiting) {
                showModalBottomSheet(
                    useRootNavigator: true,
                    isDismissible: false,
                    context: context,
                    builder: (context) {
                      return WillPopScope(
                        onWillPop: () async => false,
                        child: Center(
                          child: Text(state.msg),
                        ),
                      );
                    });
                dialog = true;
              } else {
                if (dialog) {
                  Navigator.of(context, rootNavigator: true).pop();
                  dialog = false;
                }
              }
            },
            builder: (context, state) { // some widget code... }

When the state is UserAuthorized, I want to pop the dialog as well as the LoginPage, so as to return to the last page i.e. Home page. However, with the code above, sometimes, it works, and on another time, the Home page is also popped out. I tried, with/without rootNavigator set to true, but couldn't achieve my objective.

Please help me understand what I'm missing here.

I have checked the answer here How to dismiss flutter dialog? .

ronbm
  • 147
  • 2
  • 8

2 Answers2

8

You can simply use

Navigator.popUntil(context, (route) {
            return count++ == 2;
          });

UPDATE:

If you don't know how many page you should pop then you should use

Navigator.push(context, MaterialPageRoute(builder: (context)=>YourMaterialClassName(), settings: RouteSettings(name: "nameOfYourClass")));

while you push your material class.

then in the time of poping up use

Navigator.popUntil(context, (route) => route.settings.name == "nameOfYourClass");
Tipu Sultan
  • 1,743
  • 11
  • 20
  • 1
    I could really make use of your suggestion. Helped me dig a little further into the mechanism. I tried the second code (which I think is cleaner). However I could achieve my objective with an additional Navigator.pop(context) after Navigator.popUntil, as all routes are popping out except my Login page. I think Navigator.popUntil means keep popping out routes, and stop when predicate returns true; so it stops at Login page. Let me know if my though is correct. – ronbm Aug 19 '20 at 06:25
3

I suggest after the dialog return true, instead of using Navigator.of(context).pop().

Or you can try using

Navigator.of(context).pushReplacement(
  MaterialPageRoute(builder: (context) => HomePage()),
)

By doing so you replace the LoginPage with HomePage.

Vahid
  • 6,639
  • 5
  • 37
  • 61
Aldy Yuan
  • 1,795
  • 9
  • 23
  • **pushReplacement will clear the backstack.** For Example, user navigates from Screen 1 > Screen 2 with dialog -> Screen 3. Calling Navigator.pop() in screen 3 will result to a blank/black screen since the history of going from screen 1 to screen 2 is cleared. He can't go back to screen 2 or 1. – CoderUni Aug 19 '20 at 04:03
  • I mean why would you go back to LoginPage anyway, if you not logged out IMO, but if the case you won't the screen history cleared, then I'm not suggesting this answer – Aldy Yuan Aug 19 '20 at 04:06
  • That's true but what if he wants to Navigator.pop(). There are reason one wants to Navigator.pop(). Tbh, he shouldn't be using Navigator to leave the login page in the first place. He should be using streams to get the current login state of the user. I get your point as well @Aldy Yuan, but we should give him options to call Navigator.pop() when he wants to. – CoderUni Aug 19 '20 at 04:09
  • I agree with using stream would be so much easier and avoid boilerplate, and also I agree with him want Navigator.pop() instead of pushReplacements. This only suggestion come to mine, I'll delete it soon thanks anyway – Aldy Yuan Aug 19 '20 at 04:15
  • you can keep your answer here. he can choose to use your answer if he wants. – CoderUni Aug 19 '20 at 04:17
  • I use this for a different use case, in the same app for which I posted the question, for routes of equal rank, but exclusive of each other. – ronbm Aug 19 '20 at 06:27