【问题标题】:Flutter - Navigate in PopupMenuButton onTap does not workFlutter - 在 PopupMenuButton 中导航 onTap 不起作用
【发布时间】:2021-12-08 13:27:35
【问题描述】:

我曾经使用 IconButton 的 onpressed 从我的 AppBar 导航到设置页面,这很有效。 现在我试图从 PopupMenuItem 的 onTap 触发导航,但页面无法导航。两个小部件都在同一个层次结构中,我无法找出不同行为的原因。不会抛出任何错误。

这是我的 appBar 的代码,其中包含操作:

  Widget build(BuildContext ctx) {
    return Container(
      child: Scaffold(
        appBar: AppBar(
          title: const Text('MyApp'),
          actions: [
            PopupMenuButton(
              itemBuilder: (context) => [
// THE NAVIGATION IN onTap DOES NOT WORK
                PopupMenuItem(
                  child: Text(AppLocalizations.of(context).settings),
                  onTap: () => _openSettings(ctx),
                ),
              ],
              icon: Icon(
                Icons.settings,
              ),
            ),
// THIS WORKS
            IconButton(onPressed: () => _openSettings(ctx), 
                            icon: Icon(Icons.settings))
          ],
        ),
        body: Text("")  
      ),
    );
  }

这里的导航调用只在 IconButton 的 onpressed 中起作用。 不过,我可以确认在这两种情况下都触发了该功能:

  Future<void> _openSettings(BuildContext ctx) async {
    print('settings');
    await  Navigator.push(
        ctx, MaterialPageRoute(builder: (ctx) => SettingsPage()));
    print('settings completed');
  }

如果有任何帮助,我将不胜感激!

解决方法: 我还没有发现 onTap 导航的问题是什么,但现在我只是使用 onSelected 导致相同的用户体验和工作:

Widget build(BuildContext ctx) {
    return Container(
      child: Scaffold(
        appBar: AppBar(
          title: const Text('MyApp'),
          actions: [
            PopupMenuButton(
              onSelected: (result){
                switch(result){
                  case 0: _openSettings(); break;
                  case 1: _signOut(); break;
                }
              },
              itemBuilder: (context) => [
                PopupMenuItem(
                  child: Text(AppLocalizations.of(context).settings),
                value: 0
                ),
                PopupMenuItem(
                  child: Text(AppLocalizations.of(context).logout),
                  value: 1
                )
              ],
              icon: Icon(
                Icons.settings,
              ),
            )
          ],
        )
      )
    );
 }

【问题讨论】:

  • 您可以尝试将contextitemBuilder 传递到_openSettings() 吗?所以你可以将正确的context 传递给导航器

标签: flutter dart flutter-navigation


【解决方案1】:

您需要使用()=&gt; 调用future 函数,并传递Build Context 以使函数知道从哪个上下文导航。

所以你的按钮会变成这样:

   IconButton(onPressed:()=> _openSettings(context), icon: Icon(Icons.settings))

你的函数应该是这样的:

Future<void> _openSettings(BuildContext ctx) async {
    print('settings');
    await Navigator.push(
        ctx, MaterialPageRoute(builder: (context) => SettingPage()));
    print('settings completed');
  }

这是我测试过的整个代码:
class PlayGround extends StatefulWidget {
  const PlayGround({Key? key}) : super(key: key);

  @override
  _PlayGroundState createState() => _PlayGroundState();
}

class _PlayGroundState extends State<PlayGround> {
  final _title =
      TextEditingController.fromValue(TextEditingValue(text: 'initialTitle'));

  @override
  void initState() {
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: const Text('MyApp'),
          actions: [
            PopupMenuButton<int>(
              itemBuilder: (context) => [
                PopupMenuItem(
                  child: Text(AppLocalizations.of(context).settings),
                  onTap: () {},
                ),
                PopupMenuItem(
                  child: Text(AppLocalizations.of(context).logout),
                  onTap: () {},
                )
              ],
              icon: Icon(
                Icons.settings,
              ),
            ),
            IconButton(
                onPressed: () => _openSettings(context),
                icon: Icon(Icons.settings))
          ],
        ),
        body: Container());
  }

  Future<void> _openSettings(BuildContext ctx) async {
    print('settings');
    await Navigator.push(
        ctx, MaterialPageRoute(builder: (context) => SettingPage()));
    print('settings completed');
  }
}

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
    );
  }
}

【讨论】:

  • onPressed 的调用之前已经有效。我将您建议的更改应用于 PopupMenuItem 中的调用,但不幸的是 onTap 调用后的导航仍然不起作用。
  • 我添加了已修复问题的代码。
  • 谢谢,这也适用于我。问题是当我将 _openSettings 调用添加到 PopupMenuItem 时(就像这里:PopupMenuItem(child: Text(AppLocalizations.of(context).settings), onTap: ()=>_openSettings(ctx), )) 不再起作用.
【解决方案2】:

我遇到了同样的问题(除了:我使用 GetX 进行导航。

我认为这是因为颤振会自动关闭 PopupMenuButton,并且因为导航发生得很快,它会关闭新路由而不是菜单按钮。

我在导航方法中是这样解决的:

void edit() async {
  await Future.delayed(const Duration(milliseconds: 10));
  Get.toNamed('/new/route'); // same like Navigator.of(context).pushNamed()
}

它不漂亮...我知道。但它有效XD

【讨论】:

  • 我刚刚发现它已经足够等待 1 毫秒了
猜你喜欢
  • 1970-01-01
  • 2020-04-08
  • 2019-01-28
  • 1970-01-01
  • 1970-01-01
  • 2022-01-18
  • 1970-01-01
  • 2020-09-05
  • 1970-01-01
相关资源
最近更新 更多