In some cases, we might want to return data from a new screen. For example, saywe push a new screen that presents two options to a user. When the user taps onan option, we’ll want to inform our first screen of the user’s selection so itcan act on that information!

How can we achieve this? UsingNavigator.pop!

Directions

  • Define the home screen
  • Add a button that launches the selection screen
  • Show the selection screen with two buttons
  • When a button is tapped, close the selection screen
  • Show a snackbar on the home screen with the selection

1. Define the home screen

The home screen will display a button. When tapped, it will launch the selectionscreen!

  1. class HomeScreen extends StatelessWidget {
  2. @override
  3. Widget build(BuildContext context) {
  4. return Scaffold(
  5. appBar: AppBar(
  6. title: Text('Returning Data Demo'),
  7. ),
  8. // We'll create the SelectionButton Widget in the next step
  9. body: Center(child: SelectionButton()),
  10. );
  11. }
  12. }

2. Add a button that launches the selection screen

Now, we’ll create our SelectionButton. Our selection button will:

  • Launch the SelectionScreen when it’s tapped
  • Wait for the SelectionScreen to return a result
  1. class SelectionButton extends StatelessWidget {
  2. @override
  3. Widget build(BuildContext context) {
  4. return RaisedButton(
  5. onPressed: () {
  6. _navigateAndDisplaySelection(context);
  7. },
  8. child: Text('Pick an option, any option!'),
  9. );
  10. }
  11. // A method that launches the SelectionScreen and awaits the result from
  12. // Navigator.pop
  13. _navigateAndDisplaySelection(BuildContext context) async {
  14. // Navigator.push returns a Future that will complete after we call
  15. // Navigator.pop on the Selection Screen!
  16. final result = await Navigator.push(
  17. context,
  18. // We'll create the SelectionScreen in the next step!
  19. MaterialPageRoute(builder: (context) => SelectionScreen()),
  20. );
  21. }
  22. }

3. Show the selection screen with two buttons

Now, we’ll need to build a selection screen! It will contain two buttons. Whena user taps on a button, it should close the selection screen and let the homescreen know which button was tapped!

For now, we’ll define the UI, and figure out how to return data in the nextstep.

  1. class SelectionScreen extends StatelessWidget {
  2. @override
  3. Widget build(BuildContext context) {
  4. return Scaffold(
  5. appBar: AppBar(
  6. title: Text('Pick an option'),
  7. ),
  8. body: Center(
  9. child: Column(
  10. mainAxisAlignment: MainAxisAlignment.center,
  11. children: <Widget>[
  12. Padding(
  13. padding: const EdgeInsets.all(8.0),
  14. child: RaisedButton(
  15. onPressed: () {
  16. // Pop here with "Yep"...
  17. },
  18. child: Text('Yep!'),
  19. ),
  20. ),
  21. Padding(
  22. padding: const EdgeInsets.all(8.0),
  23. child: RaisedButton(
  24. onPressed: () {
  25. // Pop here with "Nope"
  26. },
  27. child: Text('Nope.'),
  28. ),
  29. )
  30. ],
  31. ),
  32. ),
  33. );
  34. }
  35. }

4. When a button is tapped, close the selection screen

Now, we’ll want to update the onPressed callback for both of our buttons! Inorder to return data to the first screen, we’ll need to use theNavigator.popmethod.

Navigator.pop accepts an optional second argument called result. If weprovide a result, it will be returned to the Future in our SelectionButton!

Yep button

  1. RaisedButton(
  2. onPressed: () {
  3. // Our Yep button will return "Yep!" as the result
  4. Navigator.pop(context, 'Yep!');
  5. },
  6. child: Text('Yep!'),
  7. );

Nope button

  1. RaisedButton(
  2. onPressed: () {
  3. // Our Nope button will return "Nope!" as the result
  4. Navigator.pop(context, 'Nope!');
  5. },
  6. child: Text('Nope!'),
  7. );

5. Show a snackbar on the home screen with the selection

Now that we’re launching a selection screen and awaiting the result, we’ll wantto do something with the information that’s returned!

In this case, we’ll show a Snackbar displaying the result. To do so, we’llupdate the _navigateAndDisplaySelection method in our SelectionButton.

  1. _navigateAndDisplaySelection(BuildContext context) async {
  2. final result = await Navigator.push(
  3. context,
  4. MaterialPageRoute(builder: (context) => SelectionScreen()),
  5. );
  6. // After the Selection Screen returns a result, hide any previous snackbars
  7. // and show the new result!
  8. Scaffold.of(context)
  9. ..removeCurrentSnackBar()
  10. ..showSnackBar(SnackBar(content: Text("$result")));
  11. }

Complete example

  1. import 'package:flutter/material.dart';
  2. void main() {
  3. runApp(MaterialApp(
  4. title: 'Returning Data',
  5. home: HomeScreen(),
  6. ));
  7. }
  8. class HomeScreen extends StatelessWidget {
  9. @override
  10. Widget build(BuildContext context) {
  11. return Scaffold(
  12. appBar: AppBar(
  13. title: Text('Returning Data Demo'),
  14. ),
  15. body: Center(child: SelectionButton()),
  16. );
  17. }
  18. }
  19. class SelectionButton extends StatelessWidget {
  20. @override
  21. Widget build(BuildContext context) {
  22. return RaisedButton(
  23. onPressed: () {
  24. _navigateAndDisplaySelection(context);
  25. },
  26. child: Text('Pick an option, any option!'),
  27. );
  28. }
  29. // A method that launches the SelectionScreen and awaits the result from
  30. // Navigator.pop!
  31. _navigateAndDisplaySelection(BuildContext context) async {
  32. // Navigator.push returns a Future that will complete after we call
  33. // Navigator.pop on the Selection Screen!
  34. final result = await Navigator.push(
  35. context,
  36. MaterialPageRoute(builder: (context) => SelectionScreen()),
  37. );
  38. // After the Selection Screen returns a result, hide any previous snackbars
  39. // and show the new result!
  40. Scaffold.of(context)
  41. ..removeCurrentSnackBar()
  42. ..showSnackBar(SnackBar(content: Text("$result")));
  43. }
  44. }
  45. class SelectionScreen extends StatelessWidget {
  46. @override
  47. Widget build(BuildContext context) {
  48. return Scaffold(
  49. appBar: AppBar(
  50. title: Text('Pick an option'),
  51. ),
  52. body: Center(
  53. child: Column(
  54. mainAxisAlignment: MainAxisAlignment.center,
  55. children: <Widget>[
  56. Padding(
  57. padding: const EdgeInsets.all(8.0),
  58. child: RaisedButton(
  59. onPressed: () {
  60. // Close the screen and return "Yep!" as the result
  61. Navigator.pop(context, 'Yep!');
  62. },
  63. child: Text('Yep!'),
  64. ),
  65. ),
  66. Padding(
  67. padding: const EdgeInsets.all(8.0),
  68. child: RaisedButton(
  69. onPressed: () {
  70. // Close the screen and return "Nope!" as the result
  71. Navigator.pop(context, 'Nope.');
  72. },
  73. child: Text('Nope.'),
  74. ),
  75. )
  76. ],
  77. ),
  78. ),
  79. );
  80. }
  81. }

Returning Data Demo