自定义路由切换动画
通常左右切换路由API是直接使用CupertinoPageRoute
Navigator.push(context, CupertinoPageRoute(
builder: (context)=>PageB(),
));
CupertinoPageRoute是Cupertino组件提供的iOS风格的路由切换组件,也是实现左右滑动切换的API,其中有参数PageRouteBuilder是实现切换动画的关键。
Navigator.push(
context,
PageRouteBuilder(
transitionDuration: Duration(milliseconds: 500), //动画时间为500毫秒
pageBuilder: (BuildContext context, Animation animation,
Animation secondaryAnimation) {
return FadeTransition(
//使用渐隐渐入过渡,
opacity: animation,
child: PageB(), //路由B
);
},
),
);
pageBuilder有一个animation参数,这时flutter路由管理器提供的,在路由切换时pageBuilder在每个动画帧都会被回调,因此可以通过animation对象来定义过渡动画。
无论是MaterialPageRoute、CupertinoPageRoute,还是PageRouteBuilder,都是继承自PageRoute类,而PageRouteBuilder其实只是pageRoute的一个包装,可以直接继承PageRoute类来实现路由。
class FadeRoute extends PageRoute {
FadeRoute({
required this.builder,
this.transitionDuration = const Duration(milliseconds: 300),
this.opaque = true,
this.barrierDismissible = false,
this.barrierColor,
this.barrierLabel,
this.maintainState = true,
});
final WidgetBuilder builder;
@override
final Duration transitionDuration;
@override
final bool opaque;
@override
final bool barrierDismissible;
@override
final Color barrierColor;
@override
final String barrierLabel;
@override
final bool maintainState;
@override
Widget buildPage(BuildContext context, Animation<double> animation,
Animation<double> secondaryAnimation) => builder(context);
@override
Widget buildTransitions(BuildContext context, Animation<double> animation,
Animation<double> secondaryAnimation, Widget child) {
return FadeTransition(
opacity: animation,
child: builder(context),
);
}
}
使用:
Navigator.push(context, FadeRoute(builder: (context) {
return PageB();
}));
虽然上面两种方式都可以实现自定义切换动画,但是实际使用时,优先考虑PageRouteBuilder,这样无需定义一个新的路由类,使用起来会比较方便。但是有些时候PageRouteBuilder是不能满足需求的,例如在应用过渡动画时需要读取当前路由的一些属性,这时只能通过继承PageRoute的方式。
假如只想在打开新路由时应用动画,而在返回时不使用动画,那么可以在构建过渡动画时就必须判断当前路由isActive属性是否为true:
@override
Widget buildTransitions(BuildContext context, Animation<double> animation,
Animation<double> secondaryAnimation, Widget child) {
//当前路由被激活,是打开新路由
if(isActive) {
return FadeTransition(
opacity: animation,
child: builder(context),
);
}else{
//是返回,则不应用过渡动画
return Padding(padding: EdgeInsets.zero);
}
}
这里只是简单的介绍一下自定义转场动画的原理,更详细的资料大家可以阅读这篇文章