The jump function

This section provides an example for jumping to common pages.

Ordinary jump

  Navigator.of(context).push(
    MaterialPageRoute(
      builder: (_) => NextPage1(),
    ),
  );
Copy the code

Named after the jump

Navigator.of(context).pushNamed("/router/nextPage");
Copy the code

The premise is that the routing table needs to be configured in the main entry of the program

MaterialApp(
      navigatorObservers: [UserNavigatorObserver()],
      initialRoute: "/",
      routes: {
        "/router": (context) => RouterDemo(),
        "/router/nextPage": (context) => NextPage2(),
      },
    );
Copy the code

Exit pages

Navigator.of(context).pop(); Navigation.of (context).maybepop (); // Do not exit for the last page in the stackCopy the code

Advanced usage

popAndPushNamed

Exit the current page and go to a new page

Navigator.of(context).popAndPushNamed("/router/nextPage");
Copy the code

Equivalent to the following

Navigator.of(context).pop();
Navigator.of(context).push(
  MaterialPageRoute(
    builder: (_) => NextPage1(),
  ),
);
Copy the code

PS: If the current page is the root page of the stack, will pop be executed before push and popAndPushNamed? If you look at the source code, you can see that popAndPushNamed is just pop first and then push, so the result is the same.

  @optionalTypeArgs
  Future<T> popAndPushNamed<T extends Object, TO extends Object>(
    String routeName, {
    TO result,
    Object arguments,
  }) {
    pop<TO>(result);
    return pushNamed<T>(routeName, arguments: arguments);
  }
Copy the code

pushReplacementNamed

Similar to popAndPushNamed, you exit the current page and jump to a new page. While popAndPushNamed has both the out and push animations, pushReplacementNamed has only the push animations

Navigator.of(context).pushReplacementNamed("/router/next5");
Copy the code

pushNamedAndRemoveUntil

The code “modalRoute.withName (“/”)” is to back the routing stack to the root route and jump to the “/ router/nextPage “named route. For example, if the current routing stack is [1,2,3,4], run the pushNamedAndRemoveUntil command to open new page 5, set modalroute. withName to 2, and set the routing stack to [1,2,5]. Common scenarios For example, in the personal Settings page, skip to multiple submenus and then directly return to the home page.

Navigator.of(context).pushNamedAndRemoveUntil(
                "/router/nextPage",
                ModalRoute.withName("/"),
              );
Copy the code

Modalroute.withname (“/”) (“/”); / /” /” (“/”); / /” /” (“/”); I wonder if this is a problem with the design of the Flutter route. I haven’t found a modalroute.withname alternative yet, so the back page route must be a named route.

removeRoute

Route stack removal. For example, modalRoute. of(context) can be used to obtain the current page route. If you compare it to navigater.of (context).pop(), you can remove the route from the stack as soon as you get the corresponding route object. Navigater.of (context).pop() can only remove the current routing page.

Navigator.of(context).removeRoute(ModalRoute.of(context));
Copy the code

removeRouteBelow

The same is the routing stack removal function, according to the input page route to remove the anchor point route of the last page route. For example, if the routing stack is [1,2,3,4], run removeRouteBelow(3) to change the routing stack to [1,3,4].

Navigator.of(context).removeRouteBelow(ModalRoute.of(context));
Copy the code

replace

Replace routing stack functionality, similar to pushReplacementNamed.

PS:The old route must not be currently visible

The replace method is described in the official documentation and cannot be used for top stack routing. Therefore, this method can not be used for the current route, can remove the previous or stack route.

So you can finally get the specified route and remove it from the stack using the global routing stack array history in the UserNavigatorObserver.

Navigator.of(context).replace(
    oldRoute: UserNavigatorObserver
        .history[UserNavigatorObserver.history.length - 2],
    newRoute: MaterialPageRoute(
      builder: (_) => NextPage1(),
    ),
 );
Copy the code

For example, if the routing stack is [1,2,3,4],replace(3,5) changes the routing stack to [1,2,5,4].

replaceRouteBelow

Replace routing stack functionality with removeRouteBelow. Replace input route Replaces the previous page route of the anchor point route. Finally, as with replace, it does not apply to the current page route.

Navigator.of(context).replaceRouteBelow(
  anchorRoute: UserNavigatorObserver
      .history[UserNavigatorObserver.history.length - 2],
  newRoute: MaterialPageRoute(
    builder: (_) => NextPage1(),
  ),
);
Copy the code

For example, if the routing stack is [1,2,3,4],replace(3,5) changes the routing stack to [1,5,3,4].

The parameter function

Routing also supports parameter passing between pages

Into the parameter passed

The route jump passes the desired incoming arguments through the Arguments field. We can set arguments to pass more incoming arguments to the Map object. Named routes pass arguments directly through the Arguments field. Direct routes pass Arguments directly through the Settings field created in the RouteSettings object.

  • To name the route to jump
Navigator.of(context).pushNamed(
  "/router/data2",
  arguments: {"data": "Hello"},
);
Copy the code
  • To jump to the page
Navigator.of(context).push(
  MaterialPageRoute(
    builder: (context) => ChildDataDemo4(),
    settings: RouteSettings(
      arguments: {"data": "Hello"},
    ),
  ),
);
Copy the code

The receiving page obtains data from the input parameter arguments using modalRoute.of (context).settings.

class RouterChildDateDemo2 extends StatefulWidget { @override _RouterChildDateDemo2State createState() => _RouterChildDateDemo2State(); } class _RouterChildDateDemo2State extends State<RouterChildDateDemo2> { @override Widget build(BuildContext context) { Map arguments = ModalRoute.of(context).settings.arguments; String data = arguments['data']; return Scaffold( appBar: AppBar(), body: Column( children: <Widget>[ Text("data: $data"), ], ), ); }}Copy the code
  • Construct with direct route
Navigator.of(context).push(
  MaterialPageRoute(
    builder: (context) => ChildDateDemo3("Hello"),
  ),
);
Copy the code

The data receiving page gets the incoming parameters through the widget. Of course, this way of coupling is too high, not recommended for late maintenance (although MY own projects are written so, refactoring workload is huge 😿).

class ChildDateDemo3 extends StatefulWidget { final String data; ChildDateDemo3(this.data); @override _ChildDateDemo3State createState() => _ChildDateDemo3State(); } class _ChildDateDemo3State extends State<ChildDateDemo3> { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(), body: Column( children: <Widget>[ Text("data: ${widget.data}"), ], ), ); }}Copy the code

If pass due to the context context and need to use in initState, use SchedulerBinding. Instance. AddPostFrameCallback acquisition parameters.

SchedulerBinding.instance.addPostFrameCallback((_) {
  Map arguments = ModalRoute.of(context).settings.arguments;
  cusip = arguments["cusip"];
});
Copy the code

Parameters of return

In addition to the input parameters, we certainly want to be able to get the return value as well as pass the parameters. For example, when you go to a Settings page, you get the Settings data from the previous page and display it on return (although global state management is a good substitute for this).

The route jump method has the return value Future, set the jump method to async and get the result with await.

var result = await Navigator.of(context).push(
  MaterialPageRoute(
    builder: (context) => ChildDataDemo5(),
  ),
);
setState(() {
  this.result = result.toString();
});
Copy the code

Passing in the POP method requires returning generic parameters (using a dictionary is a good data structure) when returning the result of the parent page return.

Navigator.of(context).pop({"data": "Bye"});
Copy the code

The animation transition

Replace the MaterialPageRoute with the PageRouteBuilder to do the route jump. Animation effects are realized by creating an AnimatedWidget object with transitionsBuilder. Set a SlideTransition animation below to create a side slide out effect by starting and ending offsets

Navigator.of(context).push( PageRouteBuilder( pageBuilder: (BuildContext context, Animation<double> animation1, Animation<double> animation2) { return AniDemo2(); }, transitionsBuilder: (BuildContext context, Animation<double> animation1, Animation<double> animation2, Widget child) {return SlideTransition(position: Tween<Offset>(begin: Offset(-1.0, 0.0), end: Offset(0.0, 0.0),). Animate (animation1,), child: child,); },),);Copy the code

Global route monitoring

The route also supports the listening function. NavigatorObserver allows you to obtain real-time routing information. Create a NavigatorObserver in the root component. Create a UserNavigatorObserver and inherit the NavigatorObserver to record the global stack information through the callback interface. Here’s how the NavigatorObserver callback interface triggers.

MaterialApp(
    navigatorObservers: [UserNavigatorObserver()],
    ......
)
Copy the code

Inherits NavigatorObserver and adds the global History stack information management array.

class UserNavigatorObserver extends NavigatorObserver { static List<Route<dynamic>> history = <Route<dynamic>>[]; @override void didPop(Route route, Route previousRoute) { super.didPop(route, previousRoute); history.remove(route); /// Call navigator.of (context).pop();} @override void didPush(Route Route, Route Route, Route previousRoute) { super.didPush(route, previousRoute); history.add(route); /// call navigator.of (context).push(Route()) callback @override void didRemove(Route Route, Route previousRoute) { super.didRemove(route, previousRoute); history.remove(route); /// Call navigation.of (context).removeroute (Route()) to remove a Route callback} @override void didReplace({Route newRoute, Route oldRoute}) { super.didReplace(newRoute: newRoute, oldRoute: oldRoute); history.remove(oldRoute); history.add(newRoute); Of (context).replace(oldRoute:Route("old"),newRoute:Route("new"))} @override void didStartUserGesture(Route route, Route previousRoute) { super.didStartUserGesture(route, previousRoute); } @override void didStopUserGesture() {super.didStopUserGesture(); ///iOS side gesture swipe triggers stop callback is called regardless of whether the page exits or not}}Copy the code

didPop

Call back when navigator.of (context).pop() or another offstack method is called

didPush

Call back to navigator.of (context).push(Route()) or other push methods

didRemove

Call navigator.of (context).removeroute (Route()) to remove a Route callback

didReplace

Call back to Navigator. Of (context).replace(oldRoute:Route(“old”),newRoute:Route(“new”))

didStartUserGesture

IOS Side gesture swipe triggers callback callback when a gesture starts

didStopUserGesture

The iOS side gesture swipe triggers a stop callback that is called regardless of whether the page exits

🚀 See here 🚀 for the full code

reference

  • Medium.com/flutter-com…