When I use Navigator.pushNamed(context, "/someRoute");
, there is a minimal animation which slides in the new route from the bottom of the screen (on Android, might look different on iOS).
How can I add a custom animation to this transition?
I found this article, which has some very neat sample code for unnamed routes. They implement their own class which inherits from PageRouteBuilder
and can be used like this: Navigator.push(context, SlideRightRoute(page: Screen2()))
. But a PageRouteBuilder
is not a Widget and can't be registered as a route in MaterialApp
. So I don't see how to apply this to named routes.
You need to use onGenerateRoute
in your MaterialApp
widget.
onGenerateRoute: (settings) { if (settings.name == "/someRoute") { return PageRouteBuilder( settings: settings, // Pass this to make popUntil(), pushNamedAndRemoveUntil(), works pageBuilder: (_, __, ___) => SomePage(), transitionsBuilder: (_, a, __, c) => FadeTransition(opacity: a, child: c) ); } // Unknown route return MaterialPageRoute(builder: (_) => UnknownPage()); },
I found an easy solution (inspired from this code)
First, you need to set a static GlobalKey for MaterialApp and export it
static GlobalKey mtAppKey = GlobalKey(); Widget build(BuildContext context) { return MaterialApp( key: MyApp.mtAppKey, ...
Also, you need to a custom PageRouteBuilder to handle it
Null-safety disabled
class CustomNamedPageTransition extends PageRouteBuilder { CustomNamedPageTransition( GlobalKey materialAppKey, String routeName, { Object arguments, }) : super( settings: RouteSettings( arguments: arguments, name: routeName, ), pageBuilder: ( BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation, ) { assert(materialAppKey.currentWidget != null); assert(materialAppKey.currentWidget is MaterialApp); var mtapp = materialAppKey.currentWidget as MaterialApp; var routes = mtapp.routes; assert(routes.containsKey(routeName)); return routes[routeName](context); }, transitionsBuilder: ( BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation, Widget child, ) => FadeTransition( opacity: animation, child: child, ), transitionDuration: Duration(seconds: 1), ); }
Null-safety enabled
class CustomNamedPageTransition extends PageRouteBuilder { CustomNamedPageTransition( GlobalKey materialAppKey, String routeName, { Object? arguments, }) : super( settings: RouteSettings( arguments: arguments, name: routeName, ), pageBuilder: ( BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation, ) { assert(materialAppKey.currentWidget != null); assert(materialAppKey.currentWidget is MaterialApp); var mtapp = materialAppKey.currentWidget as MaterialApp; var routes = mtapp.routes; assert(routes!.containsKey(routeName)); return routes![routeName]!(context); }, transitionsBuilder: ( BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation, Widget child, ) => FadeTransition( opacity: animation, child: child, ), transitionDuration: Duration(seconds: 1), ); }
Then, you can open your named route with
Navigator.push( context, CustomNamedPageTransition( MyApp.mtAppKey, MyRoute.routeName, ), );
or
Navigator.pushReplacement( context, CustomNamedPageTransition( MyApp.mtAppKey, MyRoute.routeName, ), );
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With