Flutter pushReplaceNamed is not working correctly

Issue

I am struggling in my app:

After the user logs in I navigate to my HomeView with pushReplaceNamed , so the user should not be able to pop (by dragging) on the HomeView because in my thought it is the root view. However that is not the case.. Even after calling pushReplaceNamed the user can still drag to pop:

I simply call:

 Navigator.pushReplacementNamed(
                          context,
                          Views.home,
                        );

On the first start of the App StartView is displayed, from there I navigate to EmailView and from there to LoginView. The code above is inside my LoginView. In all the other views I simply call pushNamed.

What am I missing here? Why can the user drag pop on HomeView?
(I know I can disable it with WillPopScope, but that does not feel right…)

This is my setup in my MaterialApp:

  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'AppFlug',
      navigatorKey: Get.key,
      theme: ThemeData(
        fontFamily: AppTextStyles.montserrat,
        primarySwatch: ColorService.createMaterialColor(
          AppColors.blue,
        ),
        backgroundColor: AppColors.white,
        scaffoldBackgroundColor: AppColors.white,
      ),
      initialRoute:
          AuthenticationService.isLoggedIn() ? Views.home : Views.start,
      onGenerateRoute: AppRouter.generateRoute,
    );
  }

And here is my AppRouter:

class AppRouter {
  static Route<dynamic> generateRoute(RouteSettings settings) {
    switch (settings.name) {
      case Views.start:
        return MaterialPageRoute(
          builder: (context) => const StartView(),
        );

      case Views.email:
        return MaterialPageRoute(
          builder: (context) => EmailView(),
        );

      case Views.signUp:
        String email = settings.arguments as String;
        return MaterialPageRoute(
          builder: (context) => SignUpView(
            email: email,
          ),
        );

      case Views.login:
        String email = settings.arguments as String;
        return MaterialPageRoute(
          builder: (context) => LoginView(
            email: email,
          ),
        );

      case Views.home:
        return MaterialPageRoute(
          builder: (context) => HomeView(),
        );

      default:
        return MaterialPageRoute(
          builder: (_) => Scaffold(
            body: Center(
              child: Text(
                'No route defined for ${settings.name}',
              ),
            ),
          ),
        );
    }
  }
}

Solution

With the help of Omar I got it working: so pushReplaceNamed is only replacing the top most route. In my case all I had to do was call:

Navigator.pushNamedAndRemoveUntil(
  context,
  Views.home,
  (route) => false,
);

To quote the doc:

To remove all the routes below the pushed route, use a [RoutePredicate] that always returns false (e.g. (Route route) => false).

Answered By – Chris

Answer Checked By – David Marino (FlutterFixes Volunteer)

Leave a Reply

Your email address will not be published. Required fields are marked *