preface
Use navigator.of (context).push(Route Route) in Flutter; The Route object is passed by the MaterialPageRoute(Builder: () {}) method. When used, the default transition animation will be added during route jumps. When you need to animate a custom Route transition, use PageRouteBuilder. This class is provided by Flutter to create a custom Route. Instantiating this class gives you a Route object.
PageRouteBuilder
Creating a custom route transition animation using PageRouteBuilder requires passing in two callback functions as parameters, one necessary parameter pageBuilder, which is used to create the page to jump to, and the other function transitionsBuilder, This function is where the transition animation is implemented.
The child parameter of transitionsBuilder is a transitionsBuilder widget returned by the pageBuilder function. The pageBuilder method is called only when the route is first built. A Flutter automatically avoids extra work because the child keeps the same instance throughout the transition.
PageRouteBuilder(
pageBuilder: (
BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
) {
return widget;
},
transitionsBuilder: (
BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
Widget child,
) {
returnchild; });Copy the code
To create a custom route, you need to inherit PageRouteBuilder and then implement the constructor of the custom route.
/ / define
class YourRoute extends PageRouteBuilder {
final Widget page;
YourRoute(this.page)
: super(
pageBuilder: (
context,
animation,
secondaryAnimation,
) {
return page;
},
transitionsBuilder: (
context,
animation,
secondaryAnimation,
child,
) {
returnchild; }); }/ / use
Navigator.of(context).push(YourRoute(NewPage()));
Copy the code
The sample
Use FirstPage and SecondPage to display the effect
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false, home: FirstPage(), ); }}class FirstPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('First Page'),
elevation: 0.0,
backgroundColor: Colors.purple,
),
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Center(
child: RaisedButton(
onPressed: () {
Navigator.of(context).push(
MaterialPageRoute(builder: (context) => SecondPage()),
);
},
child: Text('Next Page'), ), ) ], ), backgroundColor: Colors.purple, ); }}class SecondPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Second Page'),
elevation: 0.0,
backgroundColor: Colors.deepPurpleAccent,
),
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Center(
child: RaisedButton(
onPressed: () {
Navigator.pop(context);
},
child: Text('Go Back'), ), ) ], ), backgroundColor: Colors.deepPurpleAccent, ); }}Copy the code
FadeTransition
class FadeRoute extends PageRouteBuilder {
final Widget page;
FadeRoute(this.page)
: super(
pageBuilder: (
context,
animation,
secondaryAnimation,
) {
return page;
},
transitionsBuilder: (
context,
animation,
secondaryAnimation,
child,
) {
returnFadeTransition( opacity: animation, child: child, ); }); }Copy the code
ScaleTransition
class ScaleRoute extends PageRouteBuilder {
final Widget page;
ScaleRoute(this.page)
: super(
pageBuilder: (
context,
animation,
secondaryAnimation,
) {
return page;
},
transitionsBuilder: (
context,
animation,
secondaryAnimation,
child,
) {
return ScaleTransition(
alignment: Alignment.bottomLeft,
scale: Tween(
begin: 0.0,
end: 1.0,
).animate(
CurvedAnimation(
parent: animation,
curve: Curves.easeInOut,
),
),
child: child,
);
},
transitionDuration: Duration(seconds: 1)); } Navigator.of(context).push(ScaleRoute(SecondPage()));Copy the code
RotationTransition
class RotationRoute extends PageRouteBuilder {
final Widget page;
RotationRoute(this.page)
: super(
pageBuilder: (
context,
animation,
secondaryAnimation,
) {
return page;
},
transitionsBuilder: (
context,
animation,
secondaryAnimation,
child,
) {
Animation myAnimation = CurvedAnimation(
parent: animation,
curve: Curves.easeInBack,
);
return RotationTransition(
turns: myAnimation,
child: child,
);
},
transitionDuration: Duration(seconds: 1)); } Navigator.of(context).push(RotationRoute(SecondPage()));Copy the code
ScaleRotationRoute
Combine two transition animations
class ScaleRotationRoute extends PageRouteBuilder {
final Widget page;
ScaleRotationRoute(this.page)
: super(
pageBuilder: (
context,
animation,
secondaryAnimation,
) {
return page;
},
transitionsBuilder: (
context,
animation,
secondaryAnimation,
child,
) {
return ScaleTransition(
scale: animation,
child: RotationTransition(
turns: Tween(
begin: 0.0,
end: 1.0,
).animate(
CurvedAnimation(parent: animation, curve: Curves.linear),
),
child: child,
),
);
},
transitionDuration: Duration(milliseconds: 800)); } Navigator.of(context).push(ScaleRotationRoute(SecondPage()));Copy the code
TransformRoute
Create 3D effects using the Transform widget
import 'dart:math' show pi;
class TransformRoute extends PageRouteBuilder {
final Widget page;
TransformRoute(this.page)
: super(
pageBuilder: (
context,
animation,
secondaryAnimation,
) {
return page;
},
transitionsBuilder: (
context,
animation,
secondaryAnimation,
child,
) {
return Transform(
transform: Matrix4.identity()
// Similar to the 'perspective' property in CSS, determine the distance between the z=0 plane and the user
..setEntry(3.2.0.0001)
..rotateX(animation.value * pi * 2)
..rotateY(animation.value * pi * 2),
alignment: FractionalOffset.center,
child: child,
);
},
transitionDuration: Duration(seconds: 2)); } Navigator.of(context).push(TransformRoute(SecondPage()));Copy the code
EnterExitRoute
Animate both the entry and exit pages
class EnterExitRoute extends PageRouteBuilder {
final Widget enterPage;
final Widget exitPage;
EnterExitRoute(this.enterPage, this.exitPage)
: super(
pageBuilder: (
context,
animation,
secondaryAnimation,
) {
return exitPage;
},
transitionsBuilder: (
context,
animation,
secondaryAnimation,
child,
) =>
Stack(
children: [
SlideTransition(
position: Tween<Offset>(
begin: Offset(0.0.0.0),
end: Offset(1.0.0.0),
).animate(
CurvedAnimation(parent: animation, curve: Curves.easeIn),
),
child: enterPage,
),
SlideTransition(
position: Tween<Offset>(
begin: Offset(1.0.0.0),
end: Offset.zero,
).animate(
CurvedAnimation(parent: animation, curve: Curves.easeInOut),
),
child: exitPage,
)
],
),
);
}
Navigator.of(context).push(
EnterExitRoute(FirstPage(), SecondPage()),
);
Copy the code
useNavigator.pushNamed
Methods the jump
The name of the jump route is judged in onGenerateRoute, and the transition animation is added for the specific route.
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: FirstPage(),
onGenerateRoute: (settings) {
switch (settings.name) {
case '/second':
return ScaleRoute(SecondPage());
break;
default:
return null; }}); } } Navigator.pushNamed(context,'/second', arguments: {});
Copy the code
Set the global route transition animation
The default Flutter route transition animation is created by the buildTransitions method, which uses the theme.of (context).pageTransitionsTheme method. Therefore, it is possible to define a global route jump transition animation.
@override
Widget buildTransitions(context, animation, secondaryAnimation, child) {
final PageTransitionsTheme theme = Theme.of(context).pageTransitionsTheme;
return theme.buildTransitions<T>(this, context, animation, secondaryAnimation, child);
}
Copy the code
Start with a custom TransitionBuilder, and the buildTransitions method returns the jump page. Then configure the Theme’s pageTransitionsTheme and set the corresponding platform. Finally, when jumping to the page using MaterialPageRoute or CupertinoPageRoute, there will be a custom transition animation.
class ScaleTransitionBuilder extends PageTransitionsBuilder {
@override
Widget buildTransitions<T>(
route,
context,
animation,
secondaryAnimation,
child,
) {
returnScaleTransition( scale: CurvedAnimation(parent: animation, curve: Curves.easeIn), child: child, ); }}class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: FirstPage(),
theme: ThemeData(
pageTransitionsTheme: PageTransitionsTheme(
builders: {
TargetPlatform.android: ScaleTransitionBuilder(),
TargetPlatform.iOS: ScaleTransitionBuilder(),
},
),
),
);
}
}
Navigator.push(context, MaterialPageRoute(builder: (ctx) => SecondPage()));
Copy the code
Encapsulate the animation as a library
Encapsulate the custom route transition animation for easy use.
enum TransitionType {
fade,
scale,
rotate,
transform,
}
class PageTransition extends PageRouteBuilder {
PageTransition(TransitionType type, Widget page, Duration time)
: super(
pageBuilder: (
context,
animation,
secondaryAnimation,
) {
return page;
},
transitionsBuilder: (
context,
animation,
secondaryAnimation,
child,
) {
switch (type) {
case TransitionType.fade:
return FadeTransition(opacity: animation, child: child);
break;
case TransitionType.scale:
return ScaleTransition(
scale: Tween(begin: 0.0, end: 1.0).animate(
CurvedAnimation(parent: animation, curve: Curves.easeInOut),
),
child: child,
);
break;
case TransitionType.rotate:
return RotationTransition(
turns: CurvedAnimation(
parent: animation,
curve: Curves.easeInBack,
),
child: child,
);
break;
case TransitionType.transform:
returnTransform( transform: Matrix4.identity() .. setEntry(3.2.0.0001)
..rotateX(animation.value * pi * 2)
..rotateY(animation.value * pi * 2),
alignment: FractionalOffset.center,
child: child,
);
break;
default:
return child;
};
},
transitionDuration: time,
);
}
/ / use
Navigator.push(
context,
PageTransition(
TransitionType.rotate,
SecondPage(),
Duration(milliseconds: 800),),}Copy the code
The original address
Refer to the article
Animate the page switch
Everything you need to know about Flutter page route transition
Perspective on Flutter