【问题标题】:How to use navigator in flutter如何在颤振中使用导航器
【发布时间】:2022-01-18 19:29:44
【问题描述】:

我正在尝试让导航器来处理我的图标。我将所有图标放在一个列中,该列在我的所有屏幕上都存在,当我单击菜单左侧的图标时,我希望能够转到不同的屏幕。右下角的图标已被禁用,我只是用它们来指代第一页和第二页。

我已经在 MyApp 小部件中设置了一个导航器,该导航器可以路由到名为 firstpage 和 secondpage 的几个测试页面,但当我单击图标并尝试路由到另一个页面时,我会收到以下错误:

The following assertion was thrown while handling a gesture:
Navigator operation requested with a context that does not include a Navigator.

我假设我没有正确使用导航器,但我不确定我需要做什么。

main.dart

import 'package:flutter/material.dart';
import 'package:practice3/secondpage.dart';
import 'firstpage.dart';
import 'package:flutter/services.dart';
import 'persistentmenu.dart';
import 'persistentrow.dart';

void main() {
  WidgetsFlutterBinding.ensureInitialized();

  SystemChrome.setPreferredOrientations(
    [DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight],
  ).then((_) {
    runApp(const MyApp());
  });
}

class BaseWidget extends StatelessWidget {

  final Widget child;

  const BaseWidget({required this.child});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: Stack(
          children: [
            Container(child: child),
            PersistentRow(),
            PersistentMenu(),
          ],
        )
    );
  }
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      builder: (context, child) => BaseWidget(child: child!),
      initialRoute: '/',
      routes: {
        '/': (context) => FirstPage(),
        '/second': (context) => SecondPage(),
      },
    );
  }
}

persistentmenu.dart


import 'package:flutter/material.dart';
import 'firstpage.dart';
import 'secondpage.dart';

class PersistentMenu extends StatelessWidget {

 @override
 Widget build(BuildContext context) {
   return SafeArea(
     child: Align(
       alignment: Alignment.bottomLeft,
       child: Container(
         width:  80,
         height: 800,
         //margin: EdgeInsets.only(right: 25),
         color: Color.fromRGBO(2, 58, 107, 1),
         child: Column(
           mainAxisAlignment: MainAxisAlignment.spaceEvenly,
           children: <Widget>[
             IconButton(
               padding: EdgeInsets.all(0.0),
               icon: Image.asset('assets/icons/Back.png'),
               onPressed: () {
                Navigator.pushNamed(context, '/'); // Route to firstpage.dart
               },
             ),
             IconButton(
               padding: EdgeInsets.all(0.0),
               icon: Image.asset('assets/icons/tip_load.png'),
               onPressed: () {},
             ),
             IconButton(
               padding: EdgeInsets.all(0.0),
               icon: Image.asset('assets/icons/tip_eject.png'),
               onPressed: () {},
             ),
             IconButton(
               padding: EdgeInsets.all(0.0),
               icon: Image.asset('assets/icons/Light.png'),
               onPressed: () {},
             ),
             IconButton(
               padding: EdgeInsets.all(0.0),
               icon: Image.asset('assets/icons/Utility.png'),
               onPressed: () {
                 Navigator.pushNamed(context, '/second'); // Route to secondpage.dart
               },
             ),
             IconButton(
               padding: EdgeInsets.all(0.0),
               icon: Image.asset('assets/icons/Help.png'),
               onPressed: () {},
             ),
             IconButton(
               padding: EdgeInsets.all(0.0),
               icon: Image.asset('assets/icons/User.png'),
               onPressed: () {},
             ),
             IconButton(
               padding: EdgeInsets.all(0.0),
               icon: Image.asset('assets/icons/Power.png'),
               onPressed: () {},
             ),
           ],
         ),
       ),
     ),
   );
 }
}

secondpage.dart

import 'package:flutter/material.dart';

class SecondPage extends StatelessWidget {

 @override
 Widget build(BuildContext context) {
   return Scaffold(
     body: Align(
       alignment: Alignment.bottomRight,
       child: Column(
         mainAxisAlignment: MainAxisAlignment.end,
         children: <Widget>[
           ElevatedButton.icon(
             onPressed: () {
               //Navigator.pushNamed(context, '/');
             },
             icon: Icon(Icons.arrow_back_outlined),
             label: Text('Back to first Page'),
           ),
         ],
       ),
     ),
   );
 }
}

【问题讨论】:

  • 尝试从 main.dart 文件中删除构建器
  • 我也试过这个,它似乎并没有让错误消失,奇怪的是导航器在我有提升按钮的 secondpage.dart 中工作得很好。虽然这仅用于测试,但我希望左侧菜单的按钮具有相同的功能,但是当我将导航器放在按下图标时,它们不起作用。

标签: flutter android-studio dart


【解决方案1】:

我已经复制了这个错误并修复了它。阅读下文了解详细解决方案。

解释:- 实际上,当您在persistentmenu.dart 中传递“上下文”时

 onPressed: () {
              Navigator.pushNamed(
                  context,
                  '/'); // Route to firstpage.dart
            },

您正在使用“persistentmenu.dart”文件的上下文,该文件链接到“BaseWidget”buildContext 的“上下文”,简而言之,该上下文是由“MyApp”类(位于 BaseWidget 类下方)作为参数传递的因此,Navigator 无法找到 MaterialApp 的上下文并弹出错误。 现在可以有多种方法来解决它,因为您需要以某种方式将 MaterialApp Context 传递给它,以便当您使用实际翻译为的 PushNamed 时

@optionalTypeArgs
static Future<T?> pushNamed<T extends Object?>(
  BuildContext context,
  String routeName, {
  Object? arguments,
}) {
  return Navigator.of(context).pushNamed<T>(routeName, arguments: arguments);
}

因此,您可以传递 MaterialApp 上下文,或者至少传递 dart 分析器可以向上搜索的上下文并搜索 MaterialApp 的上下文(因为导航器是在 MaterialApp 中定义的)。 可以有多种方法来解决这个问题,但我解决了如下。

解决方案 只需创建一个新类来存储 MaterialApp 的 GlobalKey Context

NavigatorService.dart

import 'package:flutter/material.dart';

    class NavigationService {
      static GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
    }

如下重构“MyApp”类,只需将 MaterialApp 上下文传递给 GlobalKey。 ma​​in.dart

类 MyApp 扩展 StatelessWidget { const MyApp({Key?key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      navigatorKey: NavigationService.navigatorKey,
      debugShowCheckedModeBanner: false,
      builder: (context, child) => BaseWidget(child: child!),
      initialRoute: '/',
      routes: {
        '/': (context) => FirstPage(),
        '/second': (context) => SecondPage(),
      },
    );
  }
}

并将上述上下文替换为 Navigator.pushNamed 中使用的“上下文” firstpage.dart

IconButton(
                    padding: EdgeInsets.all(0.0),
                    icon: const Icon(Icons.label_important_rounded),
                    onPressed: () {
                      Navigator.pushNamed(
                          NavigationService.navigatorKey.currentContext!,
                          '/'); // Route to firstpage.dart
                   },
           ),

对第二页也这样做。 // 路由到 secondpage.dart 我希望这能解决问题。

【讨论】:

  • 这似乎解决了我的问题,我假设 navigatorKey.currentContext!在 MyApp 中获取我的 materialApp 的上下文,而不是在我的 persistentMenu 类中的默认上下文。我是 Flutter 的新手,所以我会更多地研究 navigator 文档,希望我不会再遇到这个问题,谢谢!
【解决方案2】:

在第二个导航器中。 pushNamed 你需要使用 '/second' 因为那是你在 main.js 中命名的路由。飞镖文件

【讨论】:

  • 我在帖子中犯了一个错误,但我已修复它。
【解决方案3】:

builder 属性在导航器下方构建,因此Navigator.of(context) 将无法找到任何内容。为了使用 Navigator,您需要另一种访问状态的方法。

  • 如果您不需要导航器下方的 BaseWidget,则只需将其添加为两个页面的基础即可。

  • 如果您需要在 Navigator 下方的 BaseWidget(因此持久元素将在转换期间保持静止),您将需要创建一个 GlobalKey&lt;NavigatorState&gt; 并将其传递给 MaterialApp 和 BaseWidget。然后,您可以通过 key.currentState! 访问 NavigatorState。

【讨论】:

  • 你能告诉我更多关于我将如何做到这一点的信息吗?将不胜感激。
猜你喜欢
  • 2020-07-14
  • 2022-11-25
  • 1970-01-01
  • 2018-10-11
  • 2021-11-24
  • 2019-02-17
  • 2021-05-21
  • 1970-01-01
  • 2019-06-04
相关资源
最近更新 更多