In this tutorial, we’re gonna build a Flutter App that can navigate to a new Screen and back to Home. In this process, we can also send data to the Screen, then return data back.
More Practice: Flutter SQLite example – CRUD Operations with ListView & sqflite plugin
Flutter App Overview
Fill in the text field Name in the Home Screen:
Click on Launch Screen Button, App turns into new Screen together with Name data:
In the new Screen, click on Greeting Button, we will navigate back to the Home Screen together with ‘Hello -Name-‘:
Navigation
Home Screen to send data
In order to navigate to a new Screen, we use the Navigator.push()
method.
The push method requires a Route
.
>> We can create our own Route
, or use the MaterialPageRoute
that transitions to the new screen using a platform-specific animation.
We want to navigate to the NewScreen
when a user clicks on RaisedButton
. We also pass the name
to the NewScreen
.
>> In build()
method, we implement onPressed
callback for the RaisedButton
:
class Home extends StatefulWidget { @override _HomeState createState() => new _HomeState(); } class _HomeState extends State{ TextEditingController _nameFieldController = new TextEditingController(); @override Widget build(BuildContext context) { return Scaffold( ... RaisedButton( child: Text('Launch Screen'), onPressed: () { _navigateToNewScreen(context); }, ), ); } _navigateToNewScreen(BuildContext context) async { Map results = await Navigator.push( context, MaterialPageRoute(builder: (context) => NewScreen(name: _nameFieldController.text)), ); } }
We will be get the data returned from NewScreen
. This is why we use StatefulWidget
that has state for update UI automatically.
New Screen
To receive data from Home Screen
NewScreen
class is a StatelessWidget
and contains name
field.
Because this is just a normal StatelessWidget
, we simply require that users creating the Screen pass through a name
. Then we have a UI using the given name
.
class NewScreen extends StatelessWidget { final String name; NewScreen({Key key, this.name}) : super(key: key); @override Widget build(BuildContext context) { return Scaffold( ... Text('$name'), ); } }
To return data back to Home Screen
We will implement the onPressed
callback and use the Navitator.pop()
method.
class NewScreen extends StatelessWidget { final String name; NewScreen({Key key, this.name}) : super(key: key); @override Widget build(BuildContext context) { return Scaffold( ... RaisedButton( onPressed: () { Navigator.pop(context, {'greeting': 'Hello $name!'}); }, child: Text('Greeting'), ), ); } }
Navigator.pop()
accepts an optional second argument called result
. It will be returned to the Future
in Home
Screen.
Home Screen to show returned data
We are launching a NewScreen and awaiting the result. When there is something returned, we get and display the result.
>> Update the _navigateToNewScreen()
method in our Home
Screen: set the _result
variable. Then we show _result
with a Text
:
class Home extends StatefulWidget { @override _HomeState createState() => new _HomeState(); } class _HomeState extends State{ TextEditingController _nameFieldController = new TextEditingController(); String _result = ''; @override Widget build(BuildContext context) { return Scaffold( ... RaisedButton( child: Text('Launch Screen'), onPressed: () { _navigateToNewScreen(context); }, ), Text('$_result'), ); } _navigateToNewScreen(BuildContext context) async { Map results = await Navigator.push( context, MaterialPageRoute(builder: (context) => NewScreen(name: _nameFieldController.text)), ); if (results.containsKey('greeting')) { _result = results['greeting']; } } }
Practice
Main
lib/main.dart
import 'package:flutter/material.dart'; import 'newscreen.dart'; class Home extends StatefulWidget { @override _HomeState createState() => new _HomeState(); } class _HomeState extends State{ TextEditingController _nameFieldController = new TextEditingController(); String _result = ''; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Navigator Example'), ), body: Container( padding: EdgeInsets.all(20.0), child: Column( children: [ TextField( controller: _nameFieldController, ), Padding( padding: EdgeInsets.all(20.0), child: RaisedButton( child: Text('Launch Screen'), onPressed: () { _navigateToNewScreen(context); }, ), ), Padding( padding: EdgeInsets.all(15.0), child: Text( '$_result', style: TextStyle( color: Colors.blue, fontSize: 22.0, ), ), ), ], ), )); } _navigateToNewScreen(BuildContext context) async { Map results = await Navigator.push( context, MaterialPageRoute(builder: (context) => NewScreen(name: _nameFieldController.text)), ); if (results.containsKey('greeting')) { _result = results['greeting']; } } }
New Screen
lib/newscreen.dart
[ Text( '$name', style: TextStyle( color: Colors.blue, fontSize: 22.0, ), ), Padding( padding: const EdgeInsets.all(8.0), child: RaisedButton( onPressed: () { Navigator.pop(context, {'greeting': 'Hello $name!'}); }, child: Text('Greeting'), ), ), ], ), ), ); } }