atereshkov
atereshkov

Reputation: 4565

How to pass data to previous screen in Flutter using Navigator? (need to handle all cases: swipe to go back, press back, etc)

Let's say I'm passing data between screens using default way with 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);

So everything goes well in that case.

And I know I can handle back button interaction (onPressed) using AppBar leading property like this:

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

But there are few options how we can return to the previous screen (back on android, swipe to go back on iOS and etc). Then what should we do to handle this?

I need to return data to the previous screen in any case.

Upvotes: 4

Views: 7809

Answers (2)

Jitesh Mohite
Jitesh Mohite

Reputation: 34270

To Disable Swipe and Back Button event which default pop current screen

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: //...

Enable swipe on

WillPopScope(
      onWillPop: null,

Note: WillPopScope doesn't override swipe gesture if onWillPop callback is null:


Swipe On/Off on condition basis

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

Upvotes: 1

Claudio Castro
Claudio Castro

Reputation: 1569

When you pass an object to a next page, it is passed by reference. That is, a pointer is passed to the position of the memory where that object is. So you have both pages pointing to the same area of memory (the same object) and any changes to that object will reflect both pages. Here's an example.

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;
  }
}

Upvotes: 3

Related Questions