Defining Custom Page Transitions in Flutter
Compatible with Navigator 2.0 & 1.0
If you take a look at how to animate a page route transition in the Flutter Cookbook, you will find a recipe for wrapping your Widget in a PageRouteBuilder
and passing it to Navigator.of(context).push
, similar to
Navigator.of(context).push(_createRoute(Page2());Route _createRoute(Widget child) {
return PageRouteBuilder(
pageBuilder: (context, animation, secondaryAnimation) => child,
transitionsBuilder: (context, animation, secondaryAnimation, child) {
// define your animation here
// TODO: return animated child
},
);
}
This approach is not very adaptive, and worse, it doesn’t even work with Navigator 2.0. Fortunately, there’s simple solution that can easily be adapted to each platform and is compatible with both Navigator 2.0 & 1.0!
In this guide, we will define a simple transition that scales and fades in & out. For this, we create a single class CustomTransitionBuilder
that extends PageTransitionsBuilder
and override the buildTransitions
method.
class CustomTransitionBuilder extends PageTransitionsBuilder {
const CustomTransitionBuilder(); @override
Widget buildTransitions<T>(
PageRoute<T> route,
BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
Widget child) { final tween = Tween(begin: 0.0, end: 1.0).chain(CurveTween(curve: Curves.ease)); return ScaleTransition(
scale: animation.drive(tween),
child: FadeTransition(opacity: animation, child: child));
}
}
As you can see, we are using the ScaleTransition
and FadeTransition
AnimatedWidget
s. We define a Tween
that begins at 0.0
and ends at 1.0
using Curves.ease
for a more natural animation. This is a very simple animation. You could also create your own complex animation widgets and use them here instead, or use animations from Flutter packages.
Now, to use our transition, we simply define our app’s PageTransitionsTheme
.
MaterialApp.router(
...
theme: ThemeData(
...
pageTransitionsTheme: const PageTransitionsTheme(
builders: {
TargetPlatform.android: CustomTransitionBuilder(),
TargetPlatform.iOS: CustomTransitionBuilder(),
TargetPlatform.macOS: CustomTransitionBuilder(),
TargetPlatform.windows: CustomTransitionBuilder(),
TargetPlatform.linux: CustomTransitionBuilder(),
},
),
),
...
),
You only have to define a builder for the platforms your custom transition targets, but you can see how adaptable this approach is. Just create a different builder for each platform that you wish to animate differently. This approach even applies the transitions in a web browser according to the platform that your app is being accessed from!
That’s all there is to it! As stated, this technique works for both navigation approaches, so I encourage you to try it out in whichever you prefer.
As always, thanks for reading. Please follow me if you’d like to learn more about Flutter.
If you are new to Navigator 2.0, check out my three part series here.