Flutter导航器的Pop方法无法正常工作

8
我昨天发现了Flutter并尝试了一下,但是我有一个问题。我按照教程实现了抽屉导航(这个),抽屉打开得很好,按钮也能正常改变,但是调用Navigator.pop(context)或Navigator.of(context).pop()时,两者的行为都像这样:
在点击“Characters”之前: Before tap 在点击“Characters”之后: After tap 我在网上搜索了一下,但是没有找到类似的问题:/ 这是我的代码:
main.dart:
import 'package:flutter/material.dart';
import 'package:dnd/home.dart';

void main() => runApp(new MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
        title: 'DnD',
        home: new Home()
    );
  }
}

home.dart:

import 'package:flutter/material.dart';
import 'package:dnd/home_fragment.dart';
import 'package:dnd/char_fragment.dart';

class Home extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return new HomeState();
  }
}

class HomeState extends State<Home> {
  int selectedDrawerIndex = 0;

  getDrawerItemWidget(int pos) {
    switch(pos) {
      case 0:
        return new HomeFragment();
      case 1:
        return new CharFragment();

      default:
        return new Text('ERROR');
    }
  }

  onSelectItem(int index) {
    setState(() => selectedDrawerIndex = index);
    print(Navigator.of(context).pop());
  }

  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'DnD',
      home: new Scaffold(
        appBar: new AppBar(
          title: new Text(
            'DnD'
          )
        ),
        drawer: new Drawer(
          child: new Column(
            children: <Widget>[
              new UserAccountsDrawerHeader(
                accountName: new Text(
                  'bla'
                ),
                accountEmail: null,
              ),
              new Column(
                children: <Widget>[
                  new ListTile(
                    title: new Text(
                      'Home'
                    ),
                    leading: new Icon(
                      Icons.home
                    ),
                    selected: 0 == selectedDrawerIndex,
                    onTap: () => onSelectItem(0),
                  ),
                  new ListTile(
                    title: new Text(
                      'Characters'
                    ),
                    leading: new Icon(
                      Icons.person
                    ),
                    selected: 1 == selectedDrawerIndex,
                    onTap: () => onSelectItem(1),
                  )
                ],
              ),
            ],
          ),
        ),
        body: getDrawerItemWidget(selectedDrawerIndex)
      )
    );
  }
}

home_fragment.dart:

import 'package:flutter/material.dart';

class HomeFragment extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new Center(
      child: new Text(
        'moin'
      )
    );
  }
}

char_fragment.dart:

import 'package:flutter/material.dart';

class CharFragment extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
      return new CharState();
    }
}

class CharState extends State<CharFragment> {
  characterNew() async {
    await showDialog<bool>(
      context: context,
      child: new AlertDialog(
        title: new Text('Create new Character?'),
        actions: <Widget>[
          new FlatButton(
            child: new Text('Yes'),
            onPressed: () => Navigator.of(context).pop(true)
          ),
          new FlatButton(
            child: new Text('No'),
            onPressed: () => Navigator.of(context).pop(false)
          )
        ],
      )
    );
  }

  @override
  Widget build(BuildContext context) {
    return new Center(
      child: new GridView.count(
        crossAxisCount: 3,
        crossAxisSpacing: 10.0,
        mainAxisSpacing: 10.0,
        children: <Widget>[
          new RaisedButton.icon(
            onPressed: characterNew,
            icon: new Icon(Icons.add, size: 80.0,),
            label: new Text('')
          )
        ],
      )
    );
  }
}
3个回答

14
你的代码有两个问题:
  1. 你使用了两次MaterialApp,应该只有一个实例,因为它保存了根配置信息。
  2. 你没有在Navigator堆栈上推送任何路由,所以你试图从空列表中弹出(也就是说,堆栈里没有任何东西可供弹出)。

为了说明问题,你正在使用setState来控制Scaffoldbody的内容,因此你正在在HomeCharaters小部件之间切换,但它们实际上不能相互看到(如果你选择Home小部件,你的Char小部件不会被构建,现在如果你选择你的Char小部件,你的Home小部件已经完全被它替换)。


不太确定你在第二点哪里出错了。但是在 Scaffold 中打开抽屉确实可以使用 pop 关闭它,即使 Navigator 栈为空。也许打开抽屉会填充 Navigator 栈?就像我说的,不太确定 :) - Kevin Walter
1
嗯,我的意思不是完全要求你“推一下就弹出”。真正令人困惑的是,使用setState替换body内容的部分不应该允许您在“弹出”时反转state - Shady Aziza
1
@aziza 和 @KevinWalter,这是来自文档的内容:当用户打开抽屉时,Flutter 会在幕后将抽屉添加到导航栈中。因此,要关闭抽屉,我们可以调用 Navigator.pop(context)。 - Blasanka
如果您使用pushReplacement,那么在导航器堆栈中就没有任何内容可以进行pop操作。 - onmyway133

8
在home.dart文件的Build方法中,尝试返回一个Scaffold而不是另一个Material App的实例。你现在在Material App的body中返回了一个Material App实例。你应该只返回Scaffold。

1
非常感谢,我只是盲目地从 main.dart 中复制粘贴过来 xD 这样就解决了! - schnavid

0

对我有效的方法是这样的

onTap: () { Scaffold.of(context).openEndDrawer(); },


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接