0

I added a ripple effect to the custom build button when the user navigates to a new page. For the display ripple effect inside the button for a while, I delayed the user navigation to the new page by 150 milliseconds as in the code snippet below.

onTap: () {
    Future.delayed(const Duration(milliseconds: 150), () {
      context.push("/SampleNextPage");
  });
},

Defining Routes

go_router 5.0.5

class Routes {
  final router = GoRouter(
      // initialLocation: "HomeTitlesPage",
      routes: [
        GoRoute(
          path: "/",
          builder: (context, state) => const SplashScreen(),
        ),
        GoRoute(
          path: "/HomePage",
          builder: (context, state) => const HomePage(),
        ),
        GoRoute(
          path: "/SampleNextPage",
          builder: (context, state) => const SampleNextPage(),
        ),
      ], observers: [
    GoRouterObserver(),
  ]);
}

GoRouterObserver

class GoRouterObserver extends NavigatorObserver {
  @override
  void didPush(Route<dynamic> route, Route<dynamic>? previousRoute) {
    print('Pushed route: ${route.str}'); //name comes back null
    if (previousRoute != null) {
      print('previousRoute: ${previousRoute.str}');
    }
  }

  @override
  void didPop(Route<dynamic> route, Route<dynamic>? previousRoute) {
    print('Poped route: ${route.str}'); //name comes back null
    if (previousRoute != null) {
      print('previousRoute: ${previousRoute.str}');
    }
  }

  @override
  void didRemove(Route<dynamic> route, Route<dynamic>? previousRoute) {
    print('Removed route: ${route.str}'); //name comes back null
    if (previousRoute != null) {
      print('previousRoute: ${previousRoute.str}');
    }
  }

  @override
  void didReplace({Route<dynamic>? newRoute, Route<dynamic>? oldRoute}) {
    print('Replaced newRoute: ${newRoute!.str}');
    print('oldRoute: ${oldRoute!.str}'); //n//name comes back null
  }
}

extension on Route<dynamic> {
  String get str => 'route(${settings.name}: ${settings.arguments})';
}

In the meantime, if the user clicks the navigation button twice then the page is pushed twice to the route tree.

Accordingly, I need to preview the ripple effect and also prevent pushing the same page twice.

Is there a way to do that?

  • Btw, a true splash screen is displayed before your app has even started... What you have named SplashScreen() here should probably better be named "LoadingScreen()" or something... – Karolina Hagegård Oct 08 '22 at 06:13
  • @KarolinaHagegård It's my fault. Thanks for pointing that out. As you said it is a "Loading screen". – Waruna Kaushalya Oct 08 '22 at 06:45

1 Answers1

0

You could make the button inactive after the user has tapped it once? This would make it impossible for them to tap it a second time!... Like this:

  bool activeButton = true;

...

        onTap: activeButton
            ? () {
                    // This requires a StatefulWidget:
                    setState(() {
                      activeButton = false;
                    });
                    Future.delayed(const Duration(milliseconds: 150), () {
                      context.push("/SampleNextPage");
                    });
                  }
            : null

Otherwise (like if for some reason, you want the button to remain active and tappable, but still not get more than one SampleNextPage pushed), you could write a condition before pushing. I don't know exactly how your GoRouterObserver works, but something like this:

        onTap: (){
                    Future.delayed(const Duration(milliseconds: 150), () {
                      if (GoRouterObserver().topRoute.path != "/SampleNextPage") {
                        context.push("/SampleNextPage");
                      }
                    });
        }

Edit

Ok, I don't understand your GoRouterObserver! It doesn't seem to observe anything, to me...

When I am in a similar situation, I use a NavigationHistoryObserver! Like this:

import 'package:navigation_history_observer/navigation_history_observer.dart';

...

        onTap: (){
                    Future.delayed(const Duration(milliseconds: 150), () {
                      if (NavigationHistoryObserver().top!.settings.name != "/SampleNextPage") {
                        context.push("/SampleNextPage");
                      }
                    });
                  }
Karolina Hagegård
  • 1,180
  • 5
  • 26
  • I think your second solution is a good way to start solving this issue. Because in the first solution, if there a many navigation buttons on one page, we need to initialize several bool variables in UI. And what do you mean by "GoRouterObserver().topRoute". My GoRouterObserver is as below. – Waruna Kaushalya Oct 08 '22 at 06:39
  • I said I didn't know exactly how your GoRouterObserver worked... ".topRoute" was just a chance-taking, knowing you would understand what I meant! But plz don't put code in a comment! If you really need me to update my answer with your GoRouterObserver, plz edit it into your question. – Karolina Hagegård Oct 08 '22 at 06:43
  • I got it . Yes, I will do it that way. – Waruna Kaushalya Oct 08 '22 at 06:54