如何查看当前路线是哪条?

时间:2018-06-12 12:20:14

标签: dart flutter

我想使用抽屉导航到不同的路线,但是如果我已经在路线上,我每次点击它时都不想打开路线的新实例,而是我希望在这种情况下新路线未打开。到目前为止,这是我的代码:

Widget build(BuildContext context){
    return new Drawer(
      child:
          new ListView(
            children: <Widget>[
              new ListTile(
                title: new Text("NewRoute"),
                onTap: () {
                    Navigator.of(context).pop;
                    Navigator.of(context).pushNamed('/NewRoute');
                }
              )
           )
     )
}

我想使用条件语句来检查我们是否在某条路线上。我知道有一种方法可以检查我们目前使用Route类的isCurrent的路线

https://docs.flutter.io/flutter/widgets/Route/isCurrent.html

虽然我不确定如何实现它。

提前谢谢!

12 个答案:

答案 0 :(得分:8)

Navigator不会公开当前路线。

你可以做的是使用Navigator.popUntil(callback)作为popUtil传递给当前Route的回调,其中包括它的名称和内容。

final newRouteName = "/NewRoute";
bool isNewRouteSameAsCurrent = false;

Navigator.popUntil(context, (route) {
  if (route.settings.name == newRouteName) {
    isNewRouteSameAsCurrent = true;
  }
  return true;
});

if (!isNewRouteSameAsCurrent) {
  Navigator.pushNamed(context, newRouteName);
}

答案 1 :(得分:8)

这是Dart扩展方法的完美用例(基于RémiRousselet的回答):

extension NavigatorStateExtension on NavigatorState {

  void pushNamedIfNotCurrent( String routeName, {Object arguments} ) {
    if (!isCurrent(routeName)) {
      pushNamed( routeName, arguments: arguments );
    }
  }

  bool isCurrent( String routeName ) {
    bool isCurrent = false;
    popUntil( (route) {
      if (route.settings.name == routeName) {
        isCurrent = true;
      }
      return true;
    } );
    return isCurrent;
  }

}

然后看起来像这样干净:

Navigator.of(context).pushNamedIfNotCurrent('/NewRoute');

答案 2 :(得分:3)

Rémi's answer确实为我提供了帮助,但是如果您像我一样是Flutter / Dart的新手,则需要一段时间才能理解。因此,这是我的版本,其中包含一些额外的检查和解释性文档:

org.apache.spark.SparkException: Job aborted due to stage failure: Task 5.0 in stage 42.0 (TID 692) had a not serializable result: org.apache.hadoop.io.IntWritable

请注意,使用/// Navigates through the application. Only replaces the top Route if it is /// different from the new Route. Always keeps the home page as base of the /// Navigator stack. New screens are pushed on the Navigator stack. When the /// user switches between non-home screens, the new screen replaces the old /// screen. In this way, the stack of screens from the drawer is never higher /// than 2. Returning to the HomeScreen is done by just popping the current /// Route. void _changeRoute(BuildContext context, String newRouteName) { // Close drawer Navigator.pop(context); // Check current screen status bool currentRouteIsHome = false; bool currentRouteIsNewRoute = false; Navigator.popUntil(context, (currentRoute) { // This is just a way to access currentRoute; the top route in the // Navigator stack. if (currentRoute.settings.name == HomeScreen.ROUTE_NAME) { currentRouteIsHome = true; } if (currentRoute.settings.name == newRouteName) { currentRouteIsNewRoute = true; } // Return true so popUntil() pops nothing. return true; }); // Switch screen if (!currentRouteIsNewRoute) { // Only switch screen if new route is different from current route. if (currentRouteIsHome) { // Navigate from home to non-home screen. Navigator.pushNamed(context, newRouteName); } else { if (newRouteName == HomeScreen.ROUTE_NAME) { // Navigate from non-home screen to home. Navigator.pop(context); } else { // Navigate from non-home screen to non-home screen. Navigator.popAndPushNamed(context, newRouteName); } } } } pushNamed的此实现要求您在popAndPushNamed参数的顶级Route中定义MaterialApp名称,如下所示:

routes:

答案 3 :(得分:2)

您可以只使用一个:

Get.currentRoute

使用此软件包:https://pub.dev/packages/get

您将获得当前路线。

但是您不需要它,因为与标准Flutter不同,Get可以防止用户不小心单击两次按钮(如果用户使用的是低成本设备,则该操作会在抽动之后发生)。 然后,您只需要使用:Get.to(Home());并准备就绪,即可完成!

当前,由于这个原因,Getx实际上对于Flutter的项目是必不可少的。 我查看了所有问题,它们很酷,但是它们通常涉及使用popUntil来访问路由,并且当其他开发人员读取您的代码时,这似乎像是骇客。 使用GetX,您将不会遇到双击问题,因为只有使用Get.to(Page(),preventDuplicates:false)明确禁用它,它才会导航到同一页面的另一个页面。 记住这是个例外,在您的情况下,您可以简单地使用: Get.to(Page());并导航至下一页,而不会出现重复路线的风险,因为防止这种情况已经成为标准。

获取当前路线似乎也涉及很多样板,使用Get可以获取当前路线的名称(即使您没有命名路线也可以为您提供名称),使用简单的Get.currenteRoute

嗯,回答这个问题有点晚了,但是我希望您和其他阅读此内容的用户喜欢

答案 4 :(得分:0)

使用以下代码检查路线是否最重要......

 Route route = MaterialPageRoute(builder: (context) => WidgetName());
 if(route.isCurrent){
 }

答案 5 :(得分:0)

我正在使用此代码。

*Route route = MaterialPageRoute(builder: (context) => Myinternet());
 print(route.isCurrent);
 if(route.isCurrent){
 }*

输出:

  

显示总是 false 当前页面找不到

答案 6 :(得分:0)

这应该给您确切的路线名称

import 'package:path/path.dart';

ModalRoute.of(context).settings.name

为避免null异常,请执行此操作

var route = ModalRoute.of(context);

if(route!=null){
    print(route.settings.name);
 }

答案 7 :(得分:0)

这是我的解决方法。

void redirect(screen){
  Navigator.popUntil(context, (route) {
    if ( route.settings.name != screen) {
      Navigator.pushNamed(context, screen);
    }
    return true;
  });
}

答案 8 :(得分:0)

ModalRoute.of(context).settings.name

是解决此问题的很好的API,但是不能在initState()中使用

答案 9 :(得分:0)

对我来说,我使用的是最懒惰的最简单的方法,因为这里没有答案可以帮助我实现主路线,我只是使用抽屉类,并将当前路线的名称传递给抽屉构造函数,如下所示:

class MyDrawer extends StatelessWidget {
final String currentRoute;
MyDrawer(this.currentRoute);

@override
Widget build(BuildContext context) {
return Drawer(
    child: ListView(
      children: <Widget>[
        InkWell(
            child: Text('secondRoute'),
            onTap: () {
              if (currentRoute != 'secondRoute')
              Navigator.push(context,
                  MaterialPageRoute(builder: (context) => secondRoute()));
            }),
        InkWell(
            child: Text('thirdRoute'),
            onTap: () {
              if (currentRoute != 'thirdRoute')
              Navigator.push(context,
                  MaterialPageRoute(builder: (context) => thirdRoute()));
            }),

在我调用MyDrawer类的路线中,我传递了当前路线的名称

drawer: MyDrawer('secondRoute'),

答案 10 :(得分:0)

这是我的解决方案。基于RémiRousselet解决方案。 唯一的区别是,可以防止剩余“最后”路线的弹出。

bool routeFound = false;
String routeName = "/myRoute";

//remove all the routes and stops if find the routeName or if is the last one
Navigator.popUntil(context, (route) {
    if (route.settings.name == routeName) {
        expenseRouteFound = true;
    }
    //print("route " + routeName + " founded in stack: " + routeFound.toString());
    //print("last remaining route into the stack: " + route.isFirst.toString());

    return routeFound || route.isFirst;
});

//print("route " + routeName + " founded in stack: " + routeFound.toString());
if (!routeFound) {
    //print("time to push the route: " + routeName + "!");
    Navigator.of(context).pushNamedAndRemoveUntil(routeName, (_)=>false);
}

答案 11 :(得分:0)

基于 Rémi Rousselet 的回答。

String? currentPath;
navigatorKey.currentState?.popUntil((route) {
  currentPath = route.settings.name;
  return true;
});