Flutter go_router中,当用户不小心双击路由按钮时,如何停止两次推送同一页面?

问题描述 投票:0回答:2

当用户导航到新页面时,我向自定义构建按钮添加了连锁反应。为了使按钮内部显示波纹效果一段时间,我将用户导航到新页面的时间延迟了 150 毫秒,如下面的代码片段所示。

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

定义路线

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})';
}

同时,如果用户单击导航按钮两次,则页面会被推送到路由树两次。

因此,我需要预览波纹效果,并防止同一页面推送两次。

有办法做到吗?

flutter routes navigation delay flutter-go-router
2个回答
0
投票

您可以在用户点击按钮一次后使按钮处于非活动状态吗?这将使他们无法再次点击它!...像这样:

  bool activeButton = true;

...

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

否则(例如,如果由于某种原因,您希望按钮保持活动状态并可点击,但仍然无法推送多个 SampleNextPage),您可以在推送之前编写一个条件。我不知道你的 GoRouterObserver 是如何工作的,但是是这样的:

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

编辑

好吧,我不明白你的GoRouterObserver!对我来说,它似乎没有观察到任何东西......

当我遇到类似情况时,我使用NavigationHistoryObserver!像这样:

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");
                      }
                    });
                  }

0
投票

我认为您试图以错误的方式解决问题。实际上,您不应该添加 150 毫秒的延迟。我知道连锁反应很漂亮,但这不是其他应用程序所做的。根据雅各布定律,人们希望我们的应用程序能够像他们已经知道的其他应用程序一样工作。

有关雅各布定律的更多信息此处

© www.soinside.com 2019 - 2024. All rights reserved.