【问题标题】:Flutter WillPopScope for nested Navigation用于嵌套导航的 Flutter WillPopScope
【发布时间】:2020-10-29 14:52:48
【问题描述】:

我有带有嵌套导航器的 Flutter 应用程序,我想在我的嵌套屏幕中使用 WillPopScope 覆盖“onBackPressed”。

假设我有MainScreenPrimaryScreenSecondaryScreenPrimaryScreen 是嵌套导航器,它有几个屏幕,如PrimaryOneScreenPrimaryTwoScreenPrimaryThreeScreen

SecondaryScreen也是一个嵌套的导航器,就像PrimaryScreen一样,它有3个屏幕。

这里是我想要实现的插图

MainScreen -> PrimaryScreen(PrimaryOneScreen -> PrimaryTwoScreen -> PrimaryThreeScreen)

当我在PrimaryTwoScreen 上的位置时,我想回到PrimaryOneScreen,并使用WillPopScope 小部件覆盖“onBackPressed”。但是当我按下返回按钮时,onWillPop 从未调用过,我的屏幕直接返回到MainScreen

这是我的代码

MainScreen.dart

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        // This is the theme of your application.
        //
        // Try running your application with "flutter run". You'll see the
        // application has a blue toolbar. Then, without quitting the app, try
        // changing the primarySwatch below to Colors.green and then invoke
        // "hot reload" (press "r" in the console where you ran "flutter run",
        // or simply save your changes to "hot reload" in a Flutter IDE).
        // Notice that the counter didn't reset back to zero; the application
        // is not restarted.
        primarySwatch: Colors.blue,
      ),
      home: MainApp(),
      onGenerateRoute: (settings){
        WidgetBuilder builder;
        switch(settings.name){
          case 'primary' :
            builder = (BuildContext _) => PrimaryScreen();
            break;
          case 'secondary' :
            builder = (BuildContext _) => SecondaryScreen();
            break;
          case 'main' :
            builder = (BuildContext _) => MainApp();
            break;
          default :
            throw Exception('Invalid route: ${settings.name}');
        }

        return MaterialPageRoute(
            builder: builder,
            settings: settings
        );
      },
    );
  }
}


class MainApp extends StatelessWidget{
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Column(
        children: <Widget>[
          FlatButton(
            onPressed: (){
              Navigator.pushNamed(context, 'primary');
            },
            child: Text('To Page Primary'),
          ),
          FlatButton(
            onPressed: (){
              Navigator.pushNamed(context, 'secondary');
            },
            child: Text('To Page Secondary'),
          )
        ],
      ),
    );
  }

}

PrimaryScreen.dart

class PrimaryScreen extends StatelessWidget{
  @override
  Widget build(BuildContext context) {
    return Navigator(
        initialRoute: 'primary/pageone',
        onGenerateRoute: (RouteSettings settings){
          WidgetBuilder builder;
          switch(settings.name){
            case 'primary/pageone' :
              builder = (BuildContext _) => PrimaryOneScreen();
              break;
            case 'primary/pagetwo' :
              builder = (BuildContext _) => PrimaryTwoScreen();
              break;
            case 'primary/pagethree' :
              builder = (BuildContext _) => PrimaryThreeScreen();
              break;
            default :
              throw Exception('Invalid route: ${settings.name}');
          }

          return MaterialPageRoute(
              builder: builder,
              settings: settings
          );
        },
      );
  }

}

PrimaryOneScreen.dart

class PrimaryOneScreen extends StatelessWidget{
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Primary Page'),
      ),
      body: Center(
        child: Column(
          children: <Widget>[
           FlatButton(
              onPressed: (){
                Navigator.pushNamed(context, 'primary/pagetwo');
              },
              child: Text('To Page Two'),
            ),
            FlatButton(
              onPressed: (){
                Navigator.pushNamed(context, 'primary/pagethree');
              },
              child: Text('To Page Three'),
            ),
          ],
        ),
      ),
    );
  }

}

PrimaryTwoScreen.dart

class PrimaryTwoScreen extends StatelessWidget{
  @override
  Widget build(BuildContext context) {
    return WillPopScope(
      onWillPop: ()async{
        print('willPopScope');
        Navigator.of(context, rootNavigator: false).pop();
        return true;
      },
      child: Scaffold(
        appBar: AppBar(
          title: Text('Secondary Page'),
        ),
        body: Center(
          child: Column(
            children: <Widget>[
              FlatButton(
                onPressed: (){
                  Navigator.pushNamed(context, 'primary/pageone');
                },
                child: Text('To Page One'),
              ),
              FlatButton(
                onPressed: (){
                  Navigator.pushNamed(context, 'primary/pagethree');
                },
                child: Text('To Page Three'),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

PrimaryThreeScreen.dart

class PrimaryThreeScreen extends StatelessWidget{
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Primary Page'),
      ),
      body: Center(
        child: Column(
          children: <Widget>[
            FlatButton(
              onPressed: (){
                Navigator.pushNamed(context, 'primary/pageone');
              },
              child: Text('To Page One'),
            ),
            FlatButton(
              onPressed: (){
                Navigator.pushNamed(context, 'primary/pagetwo');
              },
              child: Text('To Page Two'),
            )
          ],
        ),
      ),
    );
  }

}

编辑 我添加了一张图片来说明我想要实现的目标。

如何只在嵌套导航器上弹出?

谢谢!

【问题讨论】:

  • 尝试 pushReplacementNamed 而不是 pushNamed
  • 另外,您可以添加图像以获得更清晰的所需输出信息吗?
  • 我应该把 pushReplacementNamed 放在哪里?每次 pushNamed??
  • 我认为 pushReplacementNamed 不是解决方案,因为它处理了以前的路线。

标签: android flutter flutter-navigation


【解决方案1】:

试试这个链接https://medium.com/flutter-community/flutter-push-pop-push-1bb718b13c31

检查用例:pushReplacementNamed标签描述

【讨论】:

  • 我想从 PrimaryTwoScreen 回到 PrimaryOneScreen。如果我使用 pushReplacementNamed 从 PrimaryOneScreen 导航到 PrimaryTwoScreen,它将在 PrimaryTwoScreen 完成动画时处理 PrimaryOneScreen。我说的对吗?
  • 是的@fajarainul
  • 所以这不是我想要的。任何想法? @Raj Kateshiya
【解决方案2】:

当按下后退按钮时,我认为它会使用你应用的主导航器,因为它不知道嵌套导航器你想要与之交互的内容。

要解决它,您必须为您的导航器分配一个键,以便以后能够使用它。并在您使用嵌套导航器处理用户操作的小部件处添加 WillPopScope。

根据您的示例,我添加了一些代码。注意,maybePop() 函数将调用嵌套导航器小部件的 WillPopScope。如果你调用pop(),它会直接弹出,忽略你的widget的WillPopScope。

class PrimaryScreen extends StatelessWidget{
  final _navigatorKey = GlobalKey<NavigatorState>();

  @override
  Widget build(BuildContext context) {
    return WillPopScope(
        onWillPop: () async {
          if (_navigatorKey.currentState != null) {
            _navigatorKey.currentState!.maybePop();
            return false;
          }

          return true;
        },
        child: Navigator(
          key: _navigatorKey,
          initialRoute: 'primary/pageone',
          onGenerateRoute: (RouteSettings settings) {
            WidgetBuilder builder;
            switch(settings.name){
              case 'primary/pageone' :
                builder = (BuildContext _) => PrimaryOneScreen();
                break;
              case 'primary/pagetwo' :
                builder = (BuildContext _) => PrimaryTwoScreen();
                break;
              case 'primary/pagethree' :
                builder = (BuildContext _) => PrimaryThreeScreen();
                break;
              default :
                throw Exception('Invalid route: ${settings.name}');
            }

            return MaterialPageRoute(
              builder: builder,
              settings: settings
          );
        },
      ),
    );
  }

}

【讨论】:

    猜你喜欢
    • 2019-11-15
    • 2020-04-21
    • 1970-01-01
    • 2020-12-10
    • 2021-02-07
    • 2022-10-17
    • 2023-04-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多