To provide custom animations, I can either extend MaterialPageRoute or PageRouteBuilder and they both seem to do the same job. So, what's the difference between the two and which one should I use?
Here's the code snippet:
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: ElevatedButton(
onPressed: () => Navigator.push(context, Foo/BarRoute(Scaffold(appBar: AppBar()))),
child: Text('Navigate'),
),
);
}
}
class FooRoute<T> extends MaterialPageRoute<T> {
final Widget page;
FooRoute(this.page) : super(builder: (_) => page);
@override
Widget buildTransitions(_, animation, __, ___) {
return FadeTransition(opacity: animation, child: page);
}
}
class BarRoute<T> extends PageRouteBuilder<T> {
final Widget page;
BarRoute(this.page) : super(pageBuilder: (_, __, ___) => page);
@override
Widget buildTransitions(_, animation, __, ___) {
return FadeTransition(opacity: animation, child: page);
}
}
The only difference I saw was on running the app on an iOS device where MaterialPageRoute tries to insert some iOSed type sliding animation in the background.
The difference between MaterialPageRoute and PageRouteBuilder is that MaterialPageRoute already defines transition animations (animations which follow the Material design concept), while PageRouteBuilder is used to "expose" the in/out animation in a builder style.
Basically whenever you want a one-time animation you would use PageRouteBuilder. For example:
Navigator.push(
context,
PageRouteBuilder(
pageBuilder: (
context,
animation,
secondaryAnimation,
) {
return const SecondRoute();
},
transitionsBuilder: (
context,
animation,
secondaryAnimation,
child,
) {
return FadeTransition(
opacity: animation,
child: child,
);
},
),
);
When you want to define a custom transition animation that will be used across your app, the approach that will fit most would be to keep using MaterialPageRoute for your navigation. Most projects' navigation will look like:
Navigator.push(
context,
MaterialPageRoute(builder: (context) => const SomeRoute()),
);
And define the custom animation using a PageTransitionBuilder in the MaterialApp's Theme
MaterialApp(
title: 'Navigation Basics',
theme: ThemeData(
useMaterial3: true,
pageTransitionsTheme: const PageTransitionsTheme(
builders: <TargetPlatform, PageTransitionsBuilder>{
TargetPlatform.android: MyCustomPageTransitionsBuilder(),
TargetPlatform.iOS: MyCustomPageTransitionsBuilder(),
TargetPlatform.linux: MyCustomPageTransitionsBuilder(),
TargetPlatform.macOS: MyCustomPageTransitionsBuilder(),
},
),
),
This way, because we used MaterialPageRoute, it will look up the widget tree for pageTransitionsTheme for the platform currently running and use the animation defined in MyCustomPageTransitionsBuilder
You can find a full example here.
If you want even more control, subclass PageRoute and use that class instead of MaterialPageRoute. Just remember to handle things like dialogs, and different platform types, etc.
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