Navigator is used in two parts:
This section says some basic operations, if you have mastered the basic jump gesture Navigator, please move Flutter Navigator products such as usage
1. The most basic use of the route - Jump in and out
Most App contain many pages used to present different kinds of information. For example: a possible app "Product List Next", click on the item when the time will jump to the corresponding "Product Details" page.
In Flutter, the page is called route (route). Is equivalent to the routing android Activity, ios routing equivalent ViewController, then routed only a widget in the Flutter.
Jump between the two routes need to go through the following three steps
- Create two route
- Navigate to the second use route Navigator.push ()
- Return to the first route using Navigator.pop ()
1.1 create two routes
First, create two pages, as this only to demonstrate the most basic navigation functions, so each page contains only one button. Click on the first page of a button to jump to the second page, click on the second page button to return to the first page
class FirstRoute extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('First Route'),
),
body: Center(
child: RaisedButton(
child: Text('Open route'),
onPressed: () {
// 点击跳转到第二个route
},
),
),
);
}
}
class SecondRoute extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Second Route"),
),
body: Center(
child: RaisedButton(
onPressed: () {
// 点击回到第一个route
},
child: Text('Go back!'),
),
),
);
}
}
1.2 Use Navigator.push () to jump pages
We use Navigator.push () to switch the page. This method will price a new Route to route the stack, and this stack is managed by the Navigator. So routing stack is come from it? You can ship your own routing stack, or directly use the system provided MaterialPageRoute . This component can easily achieve routing jump animation.
In the method FirstRoute assembly onPress added corresponding jump codes
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => SecondRoute()),
);
}
1.3 Use Navigator.pop () to return to the previous page
We use Navigator.pop () to exit and return to SecondRoute FirstRoute, pop () method will return the current route is removed from the stack Route
In onPress method SecondRoute components, add the appropriate return codes
onPressed: () {
Navigator.pop(context);
}
The complete code is as follows:
import 'package:flutter/material.dart';
void main() {
runApp(MaterialApp(
title: 'Navigation Basics',
home: FirstRoute(),
));
}
class FirstRoute extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('First Route'),
),
body: Center(
child: RaisedButton(
child: Text('Open route'),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => SecondRoute()),
);
},
),
),
);
}
}
class SecondRoute extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Second Route"),
),
body: Center(
child: RaisedButton(
onPressed: () {
Navigator.pop(context);
},
child: Text('Go back!'),
),
),
);
}
}
2. do jump by Named Routes (routing table)
In the first section we learned how to use Navigator to do to jump in and out. However, if there is a situation many times to jump to the same page of our project, this approach would result in duplication of a lot of code. The solution is to use Named Route.
In order to use Named Routes, we want to use Navigator.pushNamed () function, we quote the example of the first section, but there are subtle differences in procedure.
- Create two route
- route definitions created
- Jump to SecondRoute use Navigator.pushNamed ()
- Return to the first page using Navigator.pop ()
2.1. Creating two Route
And the first code in the same, not repeat them here
2.2. Route definitions created
We need to add two extra in the constructor MaterialApp of property: initialRoute and routes
initialRoutes represents starting route (may be understood as a first page displays the app open), routes represent all the route except initialRoute apart. Specific code as follows
MaterialApp(
// 定义APP启动时第一个显示的页面,在本例中,initialRoute指代FirstScreen
initialRoute: '/',
routes: {
// 当navigating到‘/’ route时,构建FirstScreen widget
'/': (context) => FirstScreen(),
// 当navigating 到"/second" route, 构建SecondScreen widget.
'/second': (context) => SecondScreen(),
},
);
It can be seen only when the use Named Routes Route to each defines an alias, so that we can be the basis of this alias Jump
2.3.Navigate to SecondScreen
Use Navigator.pushNamed () to jump when this method is called, routes Flutter would go to an alias defined in the corresponding route, and jump
onPressed: () {
// 跳转到SecondScreen
Navigator.pushNamed(context, '/second');
}
2.4 exit pages
Use Navigator.pop ()
onPressed: () {
// 从第二个页面返回
Navigator.pop(context);
}
The complete code is as follows:
import 'package:flutter/material.dart';
void main() {
runApp(MaterialApp(
title: 'Named Routes Demo',
initialRoute: '/',
routes: {
'/': (context) => FirstScreen(),
'/second': (context) => SecondScreen(),
},
));
}
class FirstScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('First Screen'),
),
body: Center(
child: RaisedButton(
child: Text('Launch screen'),
onPressed: () {
Navigator.pushNamed(context, '/second');
},
),
),
);
}
}
class SecondScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Second Screen"),
),
body: Center(
child: RaisedButton(
onPressed: () {
Navigator.pop(context);
},
child: Text('Go back!'),
),
),
);
}
}
3. traditional values in the Named Route
The previous two just to say how to jump in and out, but in the actual project development is certainly a problem of data exchange between ultimately pages.
Navigator.pushNamed () function is not a null reference, what is the source of the method
@optionalTypeArgs
static Future<T> pushNamed<T extends Object>(
BuildContext context,
//路由路径
String routeName, {
//携带的参数
Object arguments,
}) {
return Navigator.of(context).pushNamed<T>(routeName, arguments: arguments);
}
arguments are carried jump parameters, it is an Object, means that you can pass any type of argument, but how after the jump to the next page to get the value out of it, looks like there is no corresponding "key" yet. Here the traditional values and value complete step
- Ready data you want to pass
- Create a page to obtain the transfer of data
- The registration page in routes table
- Jump
3.1. Preparing the transfer of data
First, we define good data to be transferred. Here we pass two parameters, title and message, and encapsulates them in a Bean
class ScreenArguments {
final String title;
final String message;
ScreenArguments(this.title, this.message);
}
3.2. Create a page to accept the transfer of data
Create a new page to accept and display parameters passed. As we mentioned above how to get the arguments, we use ModalRoute.of () can be friends. This method can get the 3 parameters of the current routing portable.
class ExtractArgumentsScreen extends StatelessWidget {
static const routeName = '/extractArguments';
@override
Widget build(BuildContext context) {
//获取传递的参数
final ScreenArguments args = ModalRoute.of(context).settings.arguments;
return Scaffold(
appBar: AppBar(
title: Text(args.title),
),
body: Center(
child: Text(args.message),
),
);
}
}
3.3. Register a new page
Of course, the use of pushNamed sure to register the page jump routes in the table, so the ExtractArgumentsScreen registered into
MaterialApp(
routes: {
ExtractArgumentsScreen.routeName: (context) => ExtractArgumentsScreen(),
},
);
3.4 Jump
Everything is ready, we use pushNamed to achieve the jump, and ready to pass parameters in the past
RaisedButton(
child: Text("使用pushNamed携带参数跳转"),
onPressed: () {
//点击事件,触发跳转
Navigator.pushNamed(
context,
ExtractArgumentsScreen.routeName,
arguments: ScreenArguments(
'我是被传递的title',
'我是被传递的message.',
),
);
},
);
Extended: From Section 3.2 we know ModalRoute.of () can get the parameters passed to it, but our case is the use of passing parameters pushNamed, if Navigator.push () can pass parameters to get thing? For example like this:
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ExtractArgumentsScreen(),
settings: RouteSettings(
arguments: ScreenArguments(
'我是title',
'我是message.',
),
),
),
);
First answer: Both methods can be used by value ModalRoute.of () to the value, because the two final jump method will be called Future <T> push <T extends Object> (Route <T> route) , are interested can go to view source code, there is not much into details.
3.5. Another way to jump
In addition to the above mentioned we jump way, we can also use onGenerateRoute to jump by value.
In this example the value is still passed our title and Message, and packaged into a ScreenArguments entity class, page parameters need to be increased to accept a method configured to receive the two values
class PassArgumentsScreen extends StatelessWidget {
static const routeName = '/passArguments';
final String title;
final String message;
//定义一个构造方法
const PassArgumentsScreen({
Key key,
@required this.title,
@required this.message,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(title),
),
body: Center(
child: Text(message),
),
);
}
}
Add onGnerateRoute property in the MaterialApp
MaterialApp(
onGenerateRoute: (settings) {
// 判断当前route,分别进行处理
if (settings.name == PassArgumentsScreen.routeName) {
// 将settings.arguments转换为正确的类型 ScreenArguments.
final ScreenArguments args = settings.arguments;
//通过构造方法传值
return MaterialPageRoute(
builder: (context) {
return PassArgumentsScreen(
title: args.title,
message: args.message,
);
},
);
}
},
);
Then look at the code uses onGenerateRoute way to do jumps
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ExtractArgumentsScreen(),
settings: RouteSettings(
arguments: ScreenArguments(
'我是title',
'我是message.',
),
),
),
);
4. carry parameters Exit
We have learned how to jump, exit, carry parameters jump parameter passed to receive. But when a page exit parameters of how to carry it? For example, we opened a contact Select page, click a quit item after page, we need to know what choice of contact information yes.
Speaking in front of our exit pages just call Navigator.pop (context) on the line, in fact, this method also has an optional parameter, with a look at the complete code
@optionalTypeArgs
static bool pop<T extends Object>(BuildContext context, [ T result ]) {
return Navigator.of(context).pop<T>(result);
}
Here the second parameter T is carried on exit page parameters, let's take a detailed look at Navigator.pop () usage
- Create a page called HomeScreen and add a button to jump to SelectionScreen
- Creating SelectionScreen, this page contains two buttons, the effect of the page and click on Quit all carry different return values
- Receiving a return value HomeScreen and displays with a Snackbar
4.1 Creating a page called HomeScreen and add a button to jump to SelectionScreen
class SelectionButton extends StatelessWidget {
@override
Widget build(BuildContext context) {
return RaisedButton(
onPressed: () {
_navigateAndDisplaySelection(context);
},
child: Text('Pick an option, any option!'),
);
}
//点击跳转到SelectionScreen并接收返回值
_navigateAndDisplaySelection(BuildContext context) async {
// Navigator.push returns a Future that completes after calling
// Navigator.pop on the Selection Screen.
//调用Navigator.push()会返回一个Furture,根据这个Future可以接收页面返回的参数,这个下面再讲
final result = await Navigator.push(
context,
// Create the SelectionScreen in the next step.
MaterialPageRoute(builder: (context) => SelectionScreen()),
);
}
}
4.2 Creating SelectionScreen, this page contains two buttons, the effect of the page and click on Quit all carry different return values
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: () {
// 退出页面,并携带一个返回值‘Yep!'
Navigator.pop(context, 'Yep!');
},
child: Text('Yep!'),
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: RaisedButton(
onPressed: () {
// 退出页面,并携带一个返回值 "Nope"
Navigator.pop(context, 'Nope!');
},
child: Text('Nope.'),
),
)
],
),
),
);
}
}
4.3 HomeScreen return value received and displayed by a Snackbar
_navigateAndDisplaySelection(BuildContext context) async {
final result = await Navigator.push(
context,
MaterialPageRoute(builder: (context) => SelectionScreen()),
);
String value = result as String;
Scaffold.of(context)
..removeCurrentSnackBar()
..showSnackBar(SnackBar(content: Text("$value")));
}