Flutter Back button with return data

后端 未结 11 1007
长情又很酷
长情又很酷 2020-12-01 15:46

I have an interface with two buttons that pop and return true or false, like so:

onPressed: () => Navigator.pop(context, false)

I need t

相关标签:
11条回答
  • 2020-12-01 16:14

    The easier way is to wrap the body in WillPopScope, in this way it will work with the Back Button on the Top AND the Android Back Button on the Bottom.

    Here an example where both back buttons return false:

    final return = Navigator.of(context).push(MaterialPageRoute<bool>(
        builder: (BuildContext context) {
          return Scaffold(
            appBar: AppBar(
              title: Text("New Page"),
            ),
            body: WillPopScope(
              onWillPop: () async {
                 Navigator.pop(context, false);
                 return false;
              },
              child: newPageStuff(),
            ),
          );
        },
    ));
    

    In the other answers they suggested to use:

    leading: BackButton(...)

    I found that this works on with the Back Button on the Top and not with the Android one.

    I include anyway an example:

    final return = Navigator.of(context).push(MaterialPageRoute<bool>(
        builder: (BuildContext context) {
          return Scaffold(
            appBar: AppBar(
              leading: BackButton(
                onPressed: () => Navigator.pop(context, false),
              ),
              title: Text("New Page"),
            ),
            body: newPageStuff(),
          );
        },
    ));
    
    0 讨论(0)
  • 2020-12-01 16:14

    The simplest way to achieve this is to :

    In your body take a WillPopScope as the parent widget And on its onWillPop : () {} call

    Navigator.pop(context, false);
    

    onWillPop of WillPopScope will be triggered automatically when you’ll press the back button on your AppBar

    0 讨论(0)
  • 2020-12-01 16:19

    The default BackButton takes over the leading property of your AppBar so all you need to do is to override the leading property with your custom back button, for example:

    leading: IconButton(icon:Icon(Icons.chevron_left),onPressed:() => Navigator.pop(context, false),),)
    
    0 讨论(0)
  • 2020-12-01 16:21

    You can pass data/arguments from one screen to other,

    consider this example:

    screen1.dart:

    import 'package:flutter/material.dart';
    import 'screen2.dart';
    
    class Screen1 extends StatelessWidget {
      Screen1(this.indx);
    
      final int indx;
    
      @override
      Widget build(BuildContext context) {
        return new S1(indx: indx,);
      }
    }
    
    class S1 extends StatefulWidget {
      S1({Key key, this.indx}) : super(key: key);
    
      final int indx;
    
      @override
      S1State createState() => new S1State(indx);
    }
    
    class S1State extends State<VD> {
    
        int indx = 5;
    
      @override
      Widget build(BuildContext context) {
       return new Scaffold(
          appBar: new AppBar(
            leading: new IconButton(icon: const Icon(Icons.iconName), onPressed: () {
              Navigator.pushReplacement(context, new MaterialPageRoute(
                builder: (BuildContext context) => new Screen2(indx),
             ));
            }),
        ),
      );
     }
    }
    

    Screen 2:

    import 'package:flutter/material.dart';
    import 'screen2.dart';
    
    class Screen2 extends StatelessWidget {
     Screen2(this.indx);
    
     final int indx;
    
     @override
     Widget build(BuildContext context) {
           return new S2(indx: indx,);
        }
     }
    
     class S2 extends StatefulWidget {
      S2({Key key, this.indx}) : super(key: key);
    
      final int indx;
    
      @override
      S2State createState() => new S2State(indx);
      }
    
     class S2State extends State<VD> {
    
     int indx = 1;
    
      @override
          Widget build(BuildContext context) {
           return new Scaffold(
              appBar: new AppBar(
                leading: new IconButton(icon: const Icon(Icons.Icons.arrow_back), onPressed: () {
                  Navigator.pushReplacement(context, new MaterialPageRoute(
                    builder: (BuildContext context) => new Screen1(indx),
                 ));
                }),
            ),
          );
         }
        }
    

    To pass data between Screens, pass the argument/data to the Screens constructor in Navigator.pushReplacement().You can pass as many argument as you want.

    This line

    Navigator.pushReplacement(context, new MaterialPageRoute(
                        builder: (BuildContext context) => new Screen1(indx),
                     ));
    

    will go to Screen1 and call initState and build method of Screen1 so that you can get updated values.

    0 讨论(0)
  • 2020-12-01 16:21

    Return data from a screen

    You can do this with the Navigator.pop() method using the following steps:

    1. Define the home screen

    The home screen displays a button. When tapped, it launches the selection screen.

    class HomeScreen extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text('Returning Data Demo'),
          ),
          // Create the SelectionButton widget in the next step.
          body: Center(child: SelectionButton()),
        );
      }
    }
    
    1. Add a button that launches the selection screen

    Now, create the SelectionButton, which does the following:

    1. Launches the SelectionScreen when it’s tapped.
    2. Waits for the SelectionScreen to return a result.
    class SelectionButton extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return RaisedButton(
          onPressed: () {
            _navigateAndDisplaySelection(context);
          },
          child: Text('Pick an option, any option!'),
        );
      }
    
      // A method that launches the SelectionScreen and awaits the
      // result from Navigator.pop.
      _navigateAndDisplaySelection(BuildContext context) async {
        // Navigator.push returns a Future that completes after calling
        // Navigator.pop on the Selection Screen.
        final result = await Navigator.push(
          context,
          // Create the SelectionScreen in the next step.
          MaterialPageRoute(builder: (context) => SelectionScreen()),
        );
      }
    }
    
    1. Show the selection screen with two buttons

    Now, build a selection screen that contains two buttons. When a user taps a button, that app closes the selection screen and lets the home screen know which button was tapped.

    This step defines the UI. The next step adds code to return data.

    class SelectionScreen extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text('Pick an option'),
          ),
          body: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                Padding(
                  padding: const EdgeInsets.all(8.0),
                  child: RaisedButton(
                    onPressed: () {
                      // Pop here with "Yep"...
                    },
                    child: Text('Yep!'),
                  ),
                ),
                Padding(
                  padding: const EdgeInsets.all(8.0),
                  child: RaisedButton(
                    onPressed: () {
                      // Pop here with "Nope"
                    },
                    child: Text('Nope.'),
                  ),
                )
              ],
            ),
          ),
        );
      }
    }
    
    1. When a button is tapped, close the selection screen

    Now, update the onPressed() callback for both of the buttons. To return data to the first screen, use the Navigator.pop() method, which accepts an optional second argument called result. Any result is returned to the Future in the SelectionButton.

    RaisedButton(
      onPressed: () {
        // The Yep button returns "Yep!" as the result.
        Navigator.pop(context, 'Yep!');
      },
      child: Text('Yep!'),
    );
    
    1. Show a snackbar on the home screen with the selection

    Now that you’re launching a selection screen and awaiting the result, you’ll want to do something with the information that’s returned.

    In this case, show a snackbar displaying the result by using the _navigateAndDisplaySelection() method in SelectionButton:

    _navigateAndDisplaySelection(BuildContext context) async {
      final result = await Navigator.push(
        context,
        MaterialPageRoute(builder: (context) => SelectionScreen()),
      );
    
      // After the Selection Screen returns a result, hide any previous snackbars
      // and show the new result.
      Scaffold.of(context)
        ..removeCurrentSnackBar()
        ..showSnackBar(SnackBar(content: Text("$result")));
    }
    

    Interactive example

    class SelectionButton extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return RaisedButton(
          onPressed: () {
            _navigateAndDisplaySelection(context);
          },
          child: Text('Pick an option, any option!'),
        );
      }
    
      // A method that launches the SelectionScreen and awaits the result from
      // Navigator.pop.
      _navigateAndDisplaySelection(BuildContext context) async {
        // Navigator.push returns a Future that completes after calling
        // Navigator.pop on the Selection Screen.
        final result = await Navigator.push(
          context,
          MaterialPageRoute(builder: (context) => SelectionScreen()),
        );
    
        // After the Selection Screen returns a result, hide any previous snackbars
        // and show the new result.
        Scaffold.of(context)
          ..removeCurrentSnackBar()
          ..showSnackBar(SnackBar(content: Text("$result")));
      }
    }
    
    class SelectionScreen extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text('Pick an option'),
          ),
          body: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                Padding(
                  padding: const EdgeInsets.all(8.0),
                  child: RaisedButton(
                    onPressed: () {
                      // Close the screen and return "Yep!" as the result.
                      Navigator.pop(context, 'Yep!');
                    },
                    child: Text('Yep!'),
                  ),
                ),
                Padding(
                  padding: const EdgeInsets.all(8.0),
                  child: RaisedButton(
                    onPressed: () {
                      // Close the screen and return "Nope!" as the result.
                      Navigator.pop(context, 'Nope.');
                    },
                    child: Text('Nope.'),
                  ),
                )
              ],
            ),
          ),
        );
      }
    }
    

    Doc : Return data from a screen

    0 讨论(0)
  • 2020-12-01 16:25

    While you can override the back button for custom behaviors, don't.

    Instead of overriding the button with a custom pop, you should handle the null scenario. There are a few reasons why you don't want to manually override the icon:

    • The icon change on IOS and Android. On IOS it uses arrow_back_ios while android uses arrow_back
    • The icon may automatically disappear if there's no route to go back
    • Physical back button will still return null.

    Instead should do the following:

    var result = await Navigator.pushNamed<bool>(context, "/");
    if (result == null) {
      result = false;
    }
    
    0 讨论(0)
提交回复
热议问题