25

I have view with bottom navigation bar, and when you push a navbar item, a new route is pushed into view.

 final navigatorKey = GlobalKey<NavigatorState>();

 @override
  Widget build(BuildContext context) => MaterialApp(
    home: Scaffold(
      key: _scaffoldKey,
      body: _buildBody(context),
      bottomNavigationBar: _buildBottomNavigationBar(context),
    ),
  );

 void routeToView(routeIndex) {
      navigatorKey.currentState.pushNamed(pagesRouteFactories.keys.toList()[routeIndex]);
  }

I would like to prevent same route being pushed on the current view. I want to compare the current route with new route we are trying to push, and ignore pushing the route if it is same.

I want to scroll the view to the top if it is same route we are trying to push

Any ideas.

TSR
  • 17,242
  • 27
  • 93
  • 197
skjagini
  • 3,142
  • 5
  • 34
  • 63

2 Answers2

21

NavigatorState doesn't expose an API for getting the path of the current route, and Route doesn't expose an API for determining a route's path either. Routes can be (and often are) anonymous. You can find out if a given Route is on the top of the navigator stack right now using the isCurrent method, but this isn't very convenient for your use case.

https://stackoverflow.com/a/46498543/2554745

This is the closest solution I could think of:

Navigator.of(context).pushNamedAndRemoveUntil(
  "newRouteName",
  (route) => route.isCurrent && route.settings.name == "newRouteName"
      ? false
      : true);

It will pop the current route if name of the route is "newRouteName" and then push new one, else will not pop anything.

Edit: Latest flutter provides ModalRoute.of(context).settings.name to get the name of current route.

Harsh Bhikadia
  • 10,095
  • 9
  • 49
  • 70
  • 1
    this should be fine,its just that view has to load again with data. Also we are loosing scrolled position. Should I disable the navigation button once clicks on it, and only enable if the user selects another navigation button? – skjagini Jan 28 '19 at 22:26
  • 4
    store the currentRouteName whenever you push new route in a variable. and compare it before pushing. that would be your solution then. – Harsh Bhikadia Jan 29 '19 at 01:42
  • @HarshBhikadia can you suggest alternate for the pushAndRemoveUntil as well? – Jay Mungara Sep 21 '20 at 09:05
  • @HarshBhikadia i get your point. But, let say if i want to push a route like, Navigator.push(context, MaterialPageRoute(builder: (context)=>TestScreen())); So is there anyway to check if the current rout is equal to the TestScreen() or not? I am not able to figure out this one. – Jay Mungara Sep 21 '20 at 09:54
  • When you push `TestScreen` use the `Naivagtor.pushNamed` method, pass the name that you want. You can get the name (if set) of the current route as mention in the EDIT – Harsh Bhikadia Sep 21 '20 at 10:40
  • for those who are using bottombar, keep track of the onTap value, you can compare the onTap value with the value of currentIndex if you pass a parameter, so onTap: (value) { if (value != widget.focus) { onTapHandler(value); } }, – Matthew Slaton Aug 27 '21 at 03:05
2

This works for me:

    Route route = ModalRoute.of(context);
    final routeName = route?.settings?.name;
    if (routeName != null && routeName != nav) {
      Navigator.of(context).pushNamed(nav);
      print(route.settings.name);
    }
TSR
  • 17,242
  • 27
  • 93
  • 197