There are two ways of Flutter route jump: one is to use the system native jump method. The second is to use a third-party framework…
The original route
According to the official documentation, we usually use “screens” to refer to different pages (interfaces) of an application. For example, an app has a “screen” that displays a list of products, and when a user clicks on an image of an item, it jumps to a new “screen” that displays detailed information about the item.
Terminology: In Flutter, screens and pages are both called routes, collectively referred to as “route” in this article.
In Android development, an Activity is “routing”; in iOS development, a ViewController is “routing.” In Flutter, “routing” is also a Widget. How do I jump from a route to a new route?
MaterialPageRoute
The MaterialPageRoute is derived from the PageRoute class, which is an abstract class that represents a modal routing page occupying the entire screen space. It also defines the interface and properties of the transition animation during route construction and switching. MaterialPageRoute is a component provided by the Material component library, which can realize the route switching animation consistent with the style of platform page switching animation for different platforms:
- For Android, when a new page is opened, the new page slides from the bottom of the screen to the top of the screen; When you close a page, the current page slides from the top of the screen to the bottom of the screen and disappears, while the previous page is displayed.
- For iOS, when a page is opened, a new page slides from the right edge of the screen to the left until the new page is fully displayed, while the previous page slides from the current screen to the left and disappears. When you close a page, the reverse happens: the current page slides out from the right side of the screen, while the previous page slides in from the left.
MaterialPageRoute({
WidgetBuilder builder,
RouteSettings settings,
bool maintainState = true.bool fullscreenDialog = false,})Copy the code
builder
WidgetBuilder is a callback function of type WidgetBuilder that builds the details of the routing page and returns a widget. We typically implement this callback to return an instance of the new route.settings
Contains route configuration information, such as route name and initial route (home page).maintainState
: By default, when a new route is pushed, the original route is still stored in memory. If you want to release all resources occupied by the route when it is not used, you can set this parametermaintainState
To false.fullscreenDialog
Indicates whether the new routing page is a full-screen modal dialog box in iOS, iffullscreenDialog
为true
The new page will slide in from the bottom of the screen (instead of horizontally).
Navigator
Navigator is a routing management component that provides methods to open and exit the routing page. The Navigator manages a collection of active routes through a stack. The current page is usually the route to the top of the stack. Navigator provides a number of methods to manage the routing stack, and we’ll cover just two of its most common methods:
Future push(BuildContext context, Route route)
When the given route is pushed onto the stack (that is, a new page is opened), the return value is a Future object to receive the data returned when the new route is pushed off the stack (that is, closed).
bool pop(BuildContext context, [ result ])
The top of the stack is routed off the stack, and result is the data returned to the previous page when the page is closed.
There are many other methods for Navigator, such as navigator.replace, navigator.popuntil, etc. Please refer to the API documentation or SDK source notes for details. Next, we will introduce another routing concept, named routing.
Instance methods
Any static method in a Navigator class that takes context as the first argument corresponds to a Navigator instance method, For example, Navigator. Push (BuildContext context, Route Route) is equivalent to Navigator. Of (context).push(Route Route).
Navigate to a new page and back
-
Create two routes
First, let’s create two routes. This is the simplest example, each route contains only one button. Click the button on the first route to switch to the second route, and click the button on the second route to switch back to the first route.
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: () { // Navigate to second route when tapped.},),),); }}class SecondRoute extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text("Second Route"), ), body: Center( child: RaisedButton( onPressed: () { // Navigate back to first route when tapped. }, child: Text('Go back! '),),),); }}Copy the code
-
Jump to the second route with navigator.push ()
Jump to the new Route using the navigator.push () method, which adds a Route object to the Navigator stack. So where does this Route object come from? You can implement one yourself, or use the MaterialPageRoute class directly. It is very convenient to use MaterialPageRoute, and the framework already provides us with a switch animation similar to the platform native.
In the build() method of the FirstRoute widget, modify the onPressed() callback:
// Within the 'FirstRoute' widget onPressed: () { Navigator.push( context, MaterialPageRoute(builder: (context) => SecondRoute()), ); } Copy the code
-
Use navigator.pop () to fall back to the first route
How do I close the second route and roll back to the first? Using the navigator.pop () method, the pop() method removes the Route object from the Navigator stack.
The onPressed() callback on the SecondRoute widget returns the first route:
// Locate the SecondRoute widget Within the SecondRoute widget onPressed: () { Navigator.pop(context); } Copy the code
Pass the data to the new page
In the development process, we often need to be able to transfer some data when jumping to a new page. For example, passing information about the element the user clicked on.
-
Passed model data classes
class Todo { final String title; final String description; Todo(this.title, this.description); } Copy the code
-
Jump to the new page displayed
The data is received by defining the variable Todo
class DetailScreen extends StatelessWidget { // Declare a member variable to hold the Todo object final Todo todo; // The constructor needs Todo objects DetailScreen({Key key, @required this.todo}) : super(key: key); @override Widget build(BuildContext context) { // Use Todo objects to build UI return Scaffold( appBar: AppBar( title: Text(todo.title), ), body: Padding( padding: EdgeInsets.all(16.0), child: Text(todo.description), ), ); }}Copy the code
-
The original page
Navigator. Push jumps to the new page and passes in the Todo model.
void main() { runApp(MaterialApp( title: 'Passing Data', home: TodosScreen( todos: List.generate( 20, (i) => Todo( 'Todo $i'.'A description of what needs to be done for Todo $i'(), ((), ((), ((); }class TodosScreen extends StatelessWidget { final List<Todo> todos; TodosScreen({Key key, @required this.todos}) : super(key: key); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Todos'), ), body: ListView.builder( itemCount: todos.length, itemBuilder: (context, index) { return ListTile( title: Text(todos[index].title), onTap: () { // When the user clicks on the list, navigate to the DetailScreen and pass the current TOdo model to itNavigator.push( context, MaterialPageRoute( builder: (context) => DetailScreen(todo: todos[index]), ), ); }); },),); }}Copy the code
Or pass parameters using RouteSettings
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
class Todo {
final String title;
final String description;
Todo(this.title, this.description);
}
void main() {
runApp(MaterialApp(
title: 'Passing Data',
home: TodosScreen(
todos: List.generate(
20,
(i) => Todo(
'Todo $i'.'A description of what needs to be done for Todo $i'(), ((), ((), ((); }class TodosScreen extends StatelessWidget {
final List<Todo> todos;
TodosScreen({Key key, @required this.todos}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Todos'),
),
body: ListView.builder(
itemCount: todos.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(todos[index].title),
onTap: () {
// When the user clicks on the list, navigate to the DetailScreen and pass the current TOdo model to it
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => DetailScreen(),
// Pass parameters as part of the route. The DetailScreen reads the parameters from these Settings.settings: RouteSettings( arguments: todos[index], ), ), ); }); },),); }}class DetailScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
// Get routing parameters
final Todo todo = ModalRoute.of(context).settings.arguments;
return Scaffold(
appBar: AppBar(
title: Text(todo.title),
),
body: Padding(
padding: EdgeInsets.all(16.0), child: Text(todo.description),se ), ); }}Copy the code
Returns data from a page
In some cases, we need to return some data when we go back to the previous screen. For example, when we jump to a new screen, there are two options for the user to choose. When the user clicks an option, the user will be returned to the first screen, and the information of the user’s choice can be known on the first screen. You can do this using navigator.pop ().
The First page
When navigator. push jumps, the returned data is received with await and UI updates can be made with setState
import 'package:defensor/views/home/second.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
class First extends StatefulWidget {
First({Key key}) : super(key: key);
@override
_FirstState createState() => _FirstState();
}
class _FirstState extends State<First> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('First'),
),
body: Container(
child: Center(
child: CupertinoButton(
child: Text('jump'),
onPressed: () async {
var restult = await Navigator.push(context, MaterialPageRoute(builder: (context) => Second()));
// Restult is returned data
print(restult); })),),); }}Copy the code
The Second page
Use navigator.pop (context, data) to return the data in the second argument.
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
class Second extends StatefulWidget {
Second({Key key}) : super(key: key);
@override
_SecondState createState() => _SecondState();
}
class _SecondState extends State<Second> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Second'),
),
body: Container(
child: Center(
child: CupertinoButton(
child: Text('Return and transfer data'),
onPressed: () {
/ / data back
var data = 'I'm the data that comes back.'; Navigator.pop(context, data); })),),); }}Copy the code
Navigate to the routes table with the corresponding name
In the Navigation to a new page and Back section, we learned how to navigate to a new interface (Screen) by creating a new route and pushing it into the Navigator class.
However, this can lead to code duplication if we need to navigate to the same interface in many parts of the application. In this case, it is very convenient to define a named route and use it for navigation.
To use named routes, we can use the navigator.pushnamed () method. The following example shows how to use named routing to implement the functionality in the previous section.
Create two interfaces
class FirstScreen extends StatelessWidget {
/// Routing,
static const routeName = '/';
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('First Screen'),
),
body: Center(
child: RaisedButton(
child: Text('Launch screen'),
onPressed: () {
// Navigate to the second screen when tapped.},),),); }}class SecondScreen extends StatelessWidget {
/// Routing,
static const routeName = '/second';
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Second Screen"),
),
body: Center(
child: RaisedButton(
onPressed: () {
// Navigate back to first screen when tapped.
},
child: Text('Go back! '),),),); }}Copy the code
Define the routing
We need to define our route with additional attributes initialRoute and Routes for the MaterialApp constructor
The initialRoute attribute defines the route from which the application should be started. The Routes attribute defines all the available named routes and the widgets we should build when we jump to them.
MaterialApp(
// Start the application by naming the path with a slash
// In this case, the application will start from the FirstScreen Widget
initialRoute: '/',
routes: {
// When we jump to "/", build the FirstScreen Widget
FirstScreen.routeName: (context) => FirstScreen(),
// When we jump to "/second", build the SecondScreen Widget
SecondScreen.routeName: (context) => SecondScreen(),
},
);
Copy the code
Please note that
When using initialRoute, you need to make sure that you do not also define the home attribute.
Jump to the second screen
With Widgets and routes in place, we are ready to jump to the page. Here, we’ll use the navigator.pushnamed () function. This tells Flutter to build the widget we defined in the Routes table and launch the interface.
In the build() method of the FirstScreen Widget, we will update the onPressed() callback:
// In 'FirstScreen' Widget
onPressed: () {
// Use the named route to jump to the second interface
Navigator.pushNamed(context, SecondScreen.routeName);
}
Copy the code
Return to the first screen
To jump back to the first page, we can use the navigator.pop () method.
// In SecondScreen Widget
onPressed: () {
// Pop the current route from the stack
// to return to the first screen
Navigator.pop(context);
}
Copy the code
The resources:
Flutter official Chinese Website (flutter.cn/docs/get-st…)
Flutter of actual combat (book. Flutterchina. Club /)