120

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.

Javeed Ishaq
  • 6,024
  • 6
  • 41
  • 60
Darkhan
  • 2,888
  • 5
  • 20
  • 30
  • 1
    Is the sign-in screen the default route in your app? – Günter Zöchbauer Apr 26 '18 at 07:59
  • 3
    Navigator.pushReplacement() is working perfectly at my end. Can you please share the full code? – Dhrumil Shah - dhuma1981 Apr 26 '18 at 08:27
  • @GünterZöchbauer no, the default route is CheckAuth. The problem was that I had sign up screen where I had a button that pushed the sign in screen with Navigator.push. So when a user signed in and navigated back, he got back to the sign up screen. I replaced the Navigator.push with Navigator.pushReplacement, and now it works fine. Thanks! – Darkhan Apr 26 '18 at 09:18
  • @dhuma1981 yes, you are right, .pushReplacement() works fine. The problem was that I had sign up screen where I had a button that pushed the sign in screen with Navigator.push. So when a user signed in and navigated back, he got back to the sign up screen. I replaced the Navigator.push with Navigator.pushReplacement, and now it works fine. Thanks! – Darkhan Apr 26 '18 at 09:19
  • 1
    Navigator.pushReplacement( context, MaterialPageRoute( builder: (context) => HomeScreen(), ), ); Navigator.pushReplacement() is NOT working. HomeScreen is still showing back arrow icon after redirecting from current screen to HomeScreen. any other solution? Please share. – Kamlesh Feb 20 '21 at 11:42

12 Answers12

199

You need to use Navigator.pushReplacement when leaving the auth screen too. Not just when redirecting to login page.

Rémi Rousselet
  • 256,336
  • 79
  • 519
  • 432
  • 48
    `Navigator.pushReplacementNamed(context, '/route')` for named router – Aderbal Nunes Sep 18 '18 at 16:51
  • Thank you. Button page doesn't back to home when we click on the bottom back button in android. – Vignesh PV Mar 01 '19 at 06:19
  • 1
    Not working in my case, displaying back arrow on Dashboard screen. I am using this code on login screen: Navigator.of(context).poppushReplacementNamed(DashboardScreen.routeName); – Kamlesh Mar 09 '20 at 08:50
  • 2
    Navigator.pushReplacement( context, MaterialPageRoute( builder: (context) => HomeScreen(), ), ); Navigator.pushReplacement() is NOT working. HomeScreen is still showing back arrow icon after redirecting from current screen to HomeScreen. any other solution? Please share. – Kamlesh Feb 20 '21 at 11:43
  • 2
    Navigator.pushAndRemoveUntil( context, MaterialPageRoute(builder: (context) => HomeScreen()), (Route route) => false, ); Worked for me. – Kamlesh Feb 20 '21 at 11:46
  • Some may not know how to add a router. ` return MaterialApp( theme: ThemeData( primaryColor: const Color(0xff089BAB), ), home: const Login(), routes: { "/home": (context) => const HomePage(), "/profile": (context) => const Profile(), }, );` – kimoduor Dec 26 '22 at 12:29
  • In my case it was `context.pushReplacementNamed(screenName)` – Gal Bracha Jul 30 '23 at 07:03
104

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,
);
B Faley
  • 17,120
  • 43
  • 133
  • 223
  • 1
    For some odd reason, from `SplashScreen` `Navigator.of(context).pushReplacementNamed` was not working (aka leading back button in the target screen's `AppBar`), but absolutely identical call from different screen did work. Your solution works in both cases, weird. Thanks! – jujka Dec 21 '19 at 09:58
  • 5
    This is better than the other answers because even if you have multiple routes in your stack you will still not have a back button. – Philip Jan 12 '20 at 14:43
  • 1
    Thanks , I had the same problem and your answer helped me to solve it .. Thanks alot – Sana'a Al-ahdal Mar 12 '20 at 23:08
19

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.

Pullat Junaid
  • 3,224
  • 3
  • 25
  • 25
  • 2
    this is not working when ever I pressed back button( assistive touch's ) route goes back to previous page – Bawantha Mar 14 '20 at 08:20
6

Just simply add the below code:

Navigator.of(context).pushNamedAndRemoveUntil('/routeName', (route) => false);
5

I think you probably have already solved this. But you can set "automaticallyLeadingImplied: false" in the AppBar of the Scaffold you are navigating to.

5

I have resolved this by popping from current page and showing new page:

Navigator.pop(context);
Navigator.of(context).pushReplacement(MaterialPageRoute(builder: (context) => newPage));
Shohin
  • 519
  • 8
  • 11
5

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

Somnath
  • 368
  • 2
  • 9
  • 22
3

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

Jitesh Mohite
  • 31,138
  • 12
  • 157
  • 147
2

For anyone wondering there is a new argument that needs to be returned false Navigator.of(context).pushNamedAndRemoveUntil('/', (route) => false);

0
Navigator.of(context, rootNavigator: true).pop();
Navigator.pushNamed(context, '/');
Amir Aghajani
  • 367
  • 2
  • 5
  • See "[Explaining entirely code-based answers](https://meta.stackoverflow.com/q/392712/128421)". While this might be technically correct, it doesn't explain why it solves the problem or should be the selected answer. We should educate along with helping solve the problem. – the Tin Man Mar 22 '22 at 04:43
0

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.

Ulysses Alves
  • 2,297
  • 3
  • 24
  • 34
-2

if you are working with Getx state managemaent then you can try this

Get.of(()=> NewPage());