如何使用Navigator在Flutter中将数据传递回前一个屏幕?(需要处理所有情况:向右滑动返回,按下返回按钮等)

4
假设我正在使用Navigator.pop的默认方式在屏幕间传递数据:
@override
void selectUserAction(BuildContext context) async {
    final result = await Navigator.of(context).push( 
          MaterialPageRoute(builder: (context) => SelectUserPage()));
    final User selectedUser = result as UserModel;
}

Navigator.pop(context, selectedUser);

那么在这种情况下一切都很顺利。

我知道我可以使用AppBar的leading属性来处理返回按钮交互(onPressed),代码如下:

leading: IconButton(
    icon: BackButtonIcon(),
    onPressed: () {
       Navigator.pop(context, selectedUser);
    },
),

但是我们有几个选项可以返回到以前的屏幕(在Android上使用后退按钮,在iOS上滑动返回等)。那么我们应该怎么处理这个问题呢?

无论如何,我需要将数据返回到以前的屏幕。

2个回答

3

当你将一个对象传递给下一页时,它是通过引用传递的。也就是说,指向该对象所在内存位置的指针被传递。因此,两个页面都指向同一块内存区域(同一对象),对该对象的任何更改都会反映在两个页面上。以下是一个例子。

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      home: Home(),
    );
  }
}

class Home extends StatefulWidget {
  _HomeState createState() => _HomeState();
  Model model1 = Model('Page 1');
}

class _HomeState extends State<Home> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(title: Text("First Page")),
        body: Column(
          children: <Widget>[
            Center(
              child: RaisedButton(
                child: Text("GO"),
                onPressed: () {
                  Navigator.push(
                    context,
                    MaterialPageRoute(
                        builder: (context) => Page2(widget.model1)),
                  );
                },
              ),
            ),
            Text(widget.model1.myInfo)
          ],
        ));
  }
}

class Page2 extends StatefulWidget {
  Model model2;

  _Page2State createState() => _Page2State();

  Page2(this.model2);
}

class _Page2State extends State<Page2> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text("Page 2"),
        ),
        body: Column(
          children: <Widget>[
            TextField(
              onChanged: (text) {
                widget.model2.setNewInfo(text);
              },
              decoration: InputDecoration(
                hintText: 'Enter a new info here',
              ),
            ),
          ],
        ));
  }
}

class Model {
  String myInfo;

  Model(this.myInfo);
  setNewInfo(String info) {
    myInfo = info;
  }
}

1
禁用默认的滑动和返回按钮事件,以防止当前屏幕被弹出。
Widget build(BuildContext context) {
    return WillPopScope(
      onWillPop: () {
      /// If the Future returns true, the screen will popped(i.e navigate to the previous screen), If it is false, then it doesn't navigate back.
        return Future.value(false);
      },

      child: //...

启用滑动功能。
WillPopScope(
      onWillPop: null,

注意: 如果onWillPop回调函数为空,WillPopScope不会覆盖滑动手势:


基于条件的滑动开/关

WillPopScope(
  onWillPop: isLoading ? () async => false : null.

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