If the basic unit of a UI framework’s view element is a component, the basic unit of an application is a page. For applications with multiple pages to smoothly transition from one page to another, we need a unified mechanism to manage jumps between pages, often referred to as route management or navigation management.
We first need to know the target page object and, after completing the initialization of the target page, open it in the manner provided by the framework. For example, in Android/iOS we typically initiate an Intent or ViewController to open a new page with startActivity or pushViewController
1. Route management
There are two important concepts in Flutter routing management:
- Route: The Route is an abstraction of the application page. It corresponds to the Activity in Android and the ViewController in iOS, and is managed by the Navigator.
- Navigator: Navigator is a component that manages and maintains a stack-based history of page jumps through push and pop.
Depending on whether page identifiers need to be registered in advance, route management in Flutter can be divided into two ways:
- Basic routes. No advance registration is required and you need to construct your own page instance when switching pages.
- Name the route. You need to register a page identifier in advance to open a new route when switching pages.
2, the Navigator
const Navigator({
Key key,
this.pages = const <Page<dynamic>>[],
this.onPopPage,
this.initialRoute,
this.onGenerateInitialRoutes = Navigator.defaultGenerateInitialRoutes,
this.onGenerateRoute,
this.onUnknownRoute,
this.transitionDelegate = const DefaultTransitionDelegate<dynamic>(),
this.reportsRouteUpdateToEngine = false,
this.observers = const <NavigatorObserver>[],
})
Copy the code
The Navigator, inherited from the StatefulWidget, is also a widget that has a number of related static functions to help us navigate to pages and interact with data
-
Push the router information set to Navigator to realize page hopping.
-
“Of” basically gets the state of the most recent instance of the Navigator.
-
Pop navigates to a new page or returns to the previous page.
-
CanPop determines if you can navigate to a new page
-
MaybePop might navigate to a new page
-
PopAndPushNamed specifies a routing path and navigates to the new page.
-
PopUntil Executes pop repeatedly until the parameters of the function return true.
-
PushAndRemoveUntil pushes the given route to the Navigator, deleting the previous route until the parameters of the predicate return true.
-
PushNamed pushes the named route to the Navigator.
-
PushNamedAndRemoveUntil pushes the named route to the Navigator, deleting the previous route until the parameters of the predicate return true.
-
PushReplacement Indicates route replacement.
-
PushReplacementNamed This is also a replacement route operation. Push a named route to the Navigator and process the previous route after the new route completes the animation.
-
RemoveRoute deletes the Route from the Navigator and executes the route. dispose operation at the same time.
-
RemoveRouteBelow removes the Route from the Navigator and executes the route. dispose operation to replace the Route from the anchorRouter parameter passed in.
-
Replace replaces the route in the Navigator with a new route.
-
The replaceRouteBelow replaces the route in the Navigator with a new route that was passed in to the anchorRouter parameter.
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).
3, 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 Widget of the Material component library, which can implement a route switch animation that is consistent with the platform page switch animation style 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 the page is opened, the new page will slide from the right edge of the screen to the left until the new page is all displayed on the screen, while the previous page will slide from the current screen to the left of the screen and disappear; 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({
@required this.builder,
RouteSettings settings,
this.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
typedef WidgetBuilder = Widget Function(BuildContext context);
Copy the code
settings
Contains configuration information about routes, such as route name and initial route (home page)maintainState
: By default, when a new route is pushed, the original route is still saved in memory. To release all resources occupied by the route when it is not used, you can set maintainState to false.fullscreenDialog
: indicates whether the new routing page is a full-screen modal dialog. In iOS, if fullscreenDialog is true, the new page will slide in from the bottom of the screen (instead of horizontally).
4. Basic routes
The basic route used in Flutter is very similar to the way Android/iOS opens a new page. To navigate to a new page, we need to create an instance of The MaterialPageRoute and call the navigator.push method to push the new page to the top of the stack.
If we want to return to the previous page, we need to remove the page from the stack by calling the navigator.pop method
class OnePage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( body: Container( child: RaisedButton( child: Text('push two screen'), onPressed:(){ Navigator.push(context, MaterialPageRoute(builder: (BuildContext context){ return TwoPage(); })); }),),); } } class TwoPage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text(' second interface '),), body: Container(child: RaisedButton(child: Text('pop one screen'), onPressed:(){ Navigator.pop(context); }),),); }}Copy the code
5. Name routes
Basic routes are simple and flexible, applicable to scenarios with few application pages. However, in the case of a large number of pages in the application, using the basic routing method, every time we jump to a new page, we have to manually create the MaterialPageRoute instance, initialize the page, and then call the push method to open it, which is still quite troublesome
Therefore, Flutter provides another way to simplify route management by naming routes. We give the page a name, and then we can open it directly from the page name
To specify page switches by name, the application MaterialApp must first provide a page name mapping rule, namely routes, so that the Flutter knows the relationship between the name and the page Widget.
final Map<String, WidgetBuilder> routes;
typedef WidgetBuilder = Widget Function(BuildContext context);
Copy the code
The routing table is actually a Map where the key value corresponds to the page name and the value value is a WidgetBuilder callback function where we need to create the corresponding page. Once the page name is defined in the routing table, we can use navigator.pushnamed to open the page.
MaterialApp( ... / / register routing routes: {" two_page "(context) = > TwoPage (),},); // Open the page Navigator. PushNamed (context, "two_page") with the name;Copy the code
However, since routes are registered and used using strings, there is a danger: what if we open a route that does not exist?
When registering the routing table, Flutter provides the UnknownRoute attribute, which allows us to perform uniform page jump processing for UnknownRoute identifiers.
MaterialApp( ... {"two_page":(context)=>TwoPage(),}, "UnknownPage onUnknownRoute ": (RouteSettings setting) => MaterialPageRoute(builder: (context) => UnknownPage()), ); // Open the page with the name navigator.pushnamed (context, "ABC ");Copy the code
6. Page parameter transfer
Unlike basic routes, which can precisely control the target page initialization, named routes can only initialize fixed target pages with string names. To address the needs of target page initialization in different scenarios, Flutter provides a mechanism for routing parameters that can be passed when a route is opened and obtained via RouteSettings on the target page.
static Future<T> pushNamed<T extends Object>(
BuildContext context,
String routeName, {
Object arguments,
})
Copy the code
class _OnePageState extends State<OnePage> { String _msg = ""; @override Widget build(BuildContext context) { return Container( child: Column( children: [ RaisedButton( child: Text('push two screen pass parameters ',style: TextStyle(fontSize: 20),), onPressed:(){ Navigator.pushNamed(context, "two_page",arguments: "One ").then((value) => {this.setState(() {_msg = value;})});}), SizedBox(height: 20), Text(" $_msg",style:TextStyle(color: Colors.red,fontSize: 20)) ], ) ); }} class TwoPage extends StatelessWidget {@override Widget build(BuildContext context) ModalRoute.of(context).settings.arguments as String; Return Scaffold(appBar: appBar (title: Text(' second interface '),), body: Container(Child: Column(children: [ RaisedButton( child: Text('pop one screen',style: TextStyle(fontSize: 20)), onPressed:(){return navigator.pop (context,"two");}), SizedBox(height: 20), Text(" I am the first parameter passed from the interface: $msg",style:TextStyle(color: Colors.red,fontSize: 20)) ], ) ), ); }}Copy the code
Code address: github.com/SunshineBro…