在常规app开发中,肯定避免不了自定义路由动画,那么我们怎么给flutter定义路由动画呢。相信大家在谷歌搜索会出现很多定义路由动画的,但是按他们实现的动画,大部分是有一定缺陷的,
比如这种 路由动画 !!!!!!点我
按这种实现,正常进第一个页面没问题,但是如果再次使用MaterialPageRoute去下个页面,你会发现上个页面没出场动画
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
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;
final Duration transitionDuration;
final bool opaque;
final bool barrierDismissible;
final Color? barrierColor;
final String? barrierLabel;
final bool maintainState;
Widget buildPage(BuildContext context, Animation<double> animation,
Animation<double> secondaryAnimation) =>
builder(context);
Widget buildTransitions(BuildContext context, Animation<double> animation,
Animation<double> secondaryAnimation, Widget child) {
return FadeTransition(
opacity: animation,
child: builder(context),
);
}
}
// 使用跳转
Navigator.push(
context,
FadePageRoute(
builder: (context) => const RoutePage(),
),
);
// 页面二次跳转
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const DashLinePage(),
),
);
相关commit地址 !!!!!!点我
我们要处理这种情况,当然要修改当前路由动画,保证能不影响MaterialPageRoute再次使用时的逻辑。
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
// constants
import '../constants.dart';
class FadePageRoute extends PageRoute {
FadePageRoute({
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;
final Duration transitionDuration;
final bool opaque;
final bool barrierDismissible;
final Color? barrierColor;
final String? barrierLabel;
final bool maintainState;
bool isPopGestureInProgress(PageRoute<dynamic> route) {
return route.navigator!.userGestureInProgress;
}
bool canTransitionTo(TransitionRoute<dynamic> nextRoute) {
// Don't perform outgoing animation if the next route is a fullscreen dialog.
return (nextRoute is MaterialRouteTransitionMixin &&
!nextRoute.fullscreenDialog) ||
(nextRoute is CupertinoRouteTransitionMixin &&
!nextRoute.fullscreenDialog);
}
Widget buildPage(BuildContext context, Animation<double> animation,
Animation<double> secondaryAnimation) =>
builder(context);
Widget buildTransitions(BuildContext context, Animation<double> animation,
Animation<double> secondaryAnimation, Widget child) {
final bool linearTransition = isPopGestureInProgress(this);
return SlideTransition(
position: (linearTransition
? secondaryAnimation
: CurvedAnimation(
parent: secondaryAnimation,
curve: Curves.linearToEaseOut,
reverseCurve: Curves.easeInToLinear,
))
.drive(packetMiddleLeftTween), // 动画缩放值的变化
textDirection: Directionality.of(context), // 动画执行的位置关系
transformHitTests: false, // 点击事件是否落在动画后的控件上
child: FadeTransition(
opacity: animation,
child: child,
),
);
}
}
相关commit地址 !!!!!!点我