在 Flutter 中使用带有 WillPopScope 的嵌套导航器

Posted

技术标签:

【中文标题】在 Flutter 中使用带有 WillPopScope 的嵌套导航器【英文标题】:Use nested Navigator with WillPopScope in Flutter 【发布时间】:2019-11-15 08:12:50 【问题描述】:

在我的应用程序中,我想要一个自定义导航(仅更改屏幕的一部分并保留我在其中所做的事情的历史记录)。 为此,我正在使用导航器,它可以很好地用于简单导航。 但是,我想处理 android 的后退按钮。 Flutter 中显然存在一个问题,这迫使我处理 Navigator 的父小部件中的后退按钮: https://github.com/flutter/flutter/issues/14083

因此,我需要在子项中检索我的 Navigator 实例并在其上调用 pop()。我正在尝试为此使用 GlobalKey。

我现在正在尝试让它工作一段时间,并制作了一个示例项目来测试它。 这是我的代码:

import 'package:flutter/material.dart';

void main() 
  runApp(MaterialApp(title: 'Navigation Basics', home: MainWidget()));


class MainWidget extends StatelessWidget 
  final GlobalKey<NavigatorState> navigatorKey = GlobalKey();

  @override
  Widget build(BuildContext context) 
    return SafeArea(
        child: WillPopScope(
            onWillPop: () => navigatorKey.currentState.maybePop(),
            child: Scaffold(
                body: Padding(
              child: Column(
                children: <Widget>[
                  Text("Toto"),
                  Row(
                    mainAxisAlignment: MainAxisAlignment.spaceBetween,
                    children: <Widget>[
                      Expanded(
                          child: RaisedButton(
                        child: Text('First'),
                        onPressed: () 
                          navigatorKey.currentState.pushNamed('/first');
                          // Navigator.push(
                          //   context,
                          //   MaterialPageRoute(builder: (context) => SecondRoute()),
                          // );
                        ,
                      )),
                      Expanded(
                          child: RaisedButton(
                        child: Text('Second'),
                        onPressed: () 
                          navigatorKey.currentState.pushNamed('/second');
                        ,
                      ))
                    ],
                  ),
                  Expanded(
                      child: Stack(
                    children: <Widget>[
                      Container(
                        decoration: BoxDecoration(color: Colors.red),
                      ),
                      ConstrainedBox(
                          constraints: BoxConstraints.expand(),
                          child: _getNavigator()),
                    ],
                  )),
                ],
              ),
              padding: EdgeInsets.only(bottom: 50),
            ))));
  

  Navigator _getNavigator() 
    return Navigator(
        key: navigatorKey,
        initialRoute: '/',
        onGenerateRoute: (RouteSettings settings) 
          WidgetBuilder builder;
          switch (settings.name) 
            case '/':
              builder = (BuildContext _) => FirstRoute();
              break;
            case '/second':
              builder = (BuildContext _) => SecondRoute();
              break;
            default:
              throw new Exception('Invalid route: $settings.name');
          
          return new MaterialPageRoute(builder: builder, settings: settings);
        );
  


class FirstRoute extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    return Container(
      child: Column(
        children: <Widget>[
          RaisedButton(
            child: Text("GO TO FRAGMENT TWO"),
            onPressed: () => Navigator.of(context).pushNamed("/second"),
          )
        ],
      ),
      decoration: BoxDecoration(color: Colors.green),
    );
  


class SecondRoute extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    return Container(
      child: Column(
        children: <Widget>[
          RaisedButton(
            child: Text("GO TO FRAGMENT ONE"),
            onPressed: () => Navigator.of(context).pop(),
          )
        ],
      ),
      decoration: BoxDecoration(color: Colors.blue),
    );
  

但是,这并没有按我的意愿工作。默认的 Navigator 似乎仍在使用:打开 SecondRoute 并按下 Android 后退按钮后,它只是离开应用程序,而不是回到第一条路线。

我怎样才能实现我想要的?

【问题讨论】:

【参考方案1】:

按照 onWillPop 的文档:

  /// Called to veto attempts by the user to dismiss the enclosing [ModalRoute].
  ///
  /// If the callback returns a Future that resolves to false, the enclosing
  /// route will not be popped.
  final WillPopCallback onWillPop;

您的处理程序应指示不应关闭封闭路由,因此返回 false 将解决您的问题。

将您的处理程序更改为此工作:

    onWillPop: () async 
      navigatorKey.currentState.maybePop();
      return false;
    ,

【讨论】:

在使用 WillPopScope 小部件时如何让 ios 中的“向后滑动”功能正常工作?

以上是关于在 Flutter 中使用带有 WillPopScope 的嵌套导航器的主要内容,如果未能解决你的问题,请参考以下文章

Flutter - 对带有模型的图表使用 API

如何在 Bloc Login Flutter 中使用带有身份验证的 NavigationDrawer 路由

如何在 Flutter 中使用带有打印机名称的以太网 POS 打印机打印收据?

Flutter - 选择带有显示和返回值的列表

如何在 Flutter 中滚动带有粘性标题的堆叠容器?

获取错误java在flutter中使用或覆盖带有contacts_service包的已弃用API