You'll never have only one screen in your app, so, you'll need to navigate across other pages. The question is... how do I do it? Flutter makes it pretty clear with a class simply called Navigator.
If you have already some know-how about this class you can check out our tutorial on Routing here. Otherwise let's dive into Navigator
world.
Push & Pop
The two main functions of Navigator are push and pop. Push can be seen as the way to show another screen (Widget), Pop is the way to "remove" current screen and show what was present before.
Push needs a Route object which contains all the data needed to to mantain navigation across the app and also identify the animation. So we have MaterialPageRoute and CupertinoPageRoute.
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => MyWidget()
)
);
Each need to implement the builder which returns your new screen. Also there are other parameters that treat the new page as a fullscreen dialog or other settings.
Pop simply removes the top-most route off the navigator and shows the previous view. This is applied not only for "screen" widgets but also dialogs and popups, as there's no "dismiss" method for them
WillPopScope
This Widget can be wrapped around a Scaffold or any top-level tree widget. It has a onWillPop
interface which is triggered when the widget is going to be popped and, by returning a boolean, you can decide if the pop should happen or not.
This can be useful to use if you need to do certain tasks as user exits a screen or to show a confirmation dialog before exiting.
@override
Widget build(BuildContext context) {
return WillPopScope (
onWillPop: () async {
//Do some stuff
return true; //OR FALSE
},
child: Text('WillPop?'),
);
}
Await on push
Returning data from a screen can be a big requirement, eg. inserting a new car and updating a database when the user clicks "save". In Flutter there's something pretty similar to the "startActivityForResult" of Android, but easier to handle: just await on push!
Navigator.push
is a function which returns a Future
, completed when the pushed widget is popped. You can send on pop any simple data you wish and obtain it by just awaiting for the result, which will be needed to be casted as it would be a dynamic.
Here's a simple example: Screen A triggers Screen B, which shows a TextField, which written content must be shown by Screen A:
/**SCREEN A**/
String ourText;
final result = await Navigator.push(
context,
MaterialPageRoute(builder: (context) => SCREENB()),
);
if(result != null)
setState(){
ourText = result;
//THERE WILL BE A Text WIDGET THAT SHOWS IT
}
}
/**SCREEN B**/
//Show a TextField and attach a textController
ElevatedButton(
onPressed: () {
// The Yep button returns "Yep!" as the result.
Navigator.pop(context, textController.text);
},
);
As you saw navigation is pretty streamlined in Flutter. In order to maintain more order you can create a Router
, where set all Navigator
calls. Check our little guide on creating a simple router and tell us what you think!
Top comments (0)