写点什么

让页面跳转更有趣 —— 实现自定义页面切换转场动画

作者:岛上码农
  • 2022 年 4 月 04 日
  • 本文字数:2868 字

    阅读完需:约 9 分钟

让页面跳转更有趣 —— 实现自定义页面切换转场动画

fluro 转场动画源码

在使用自定义转场动画前,先扒一扒 fluro 的源码,通过源码可以发现这么一个标准的转场方法:


RouteTransitionsBuilder _standardTransitionsBuilder(      TransitionType? transitionType) {    return (BuildContext context, Animation<double> animation,        Animation<double> secondaryAnimation, Widget child) {      if (transitionType == TransitionType.fadeIn) {        return FadeTransition(opacity: animation, child: child);      } else {        const Offset topLeft = const Offset(0.0, 0.0);        const Offset topRight = const Offset(1.0, 0.0);        const Offset bottomLeft = const Offset(0.0, 1.0);
Offset startOffset = bottomLeft; Offset endOffset = topLeft; if (transitionType == TransitionType.inFromLeft) { startOffset = const Offset(-1.0, 0.0); endOffset = topLeft; } else if (transitionType == TransitionType.inFromRight) { startOffset = topRight; endOffset = topLeft; } else if (transitionType == TransitionType.inFromBottom) { startOffset = bottomLeft; endOffset = topLeft; } else if (transitionType == TransitionType.inFromTop) { startOffset = Offset(0.0, -1.0); endOffset = topLeft; }
return SlideTransition( position: Tween<Offset>( begin: startOffset, end: endOffset, ).animate(animation), child: child, ); } }; }
复制代码


从源码可以看出,根据不同枚举返回了不同的动画(即 transitionBuilder),其中TransitionType.fadeIn使用的是 Flutter 自带的 FadeTransition,通过改变透明度来完成动画。而其他的左滑入、右滑入、下滑入和上滑入都是从初始偏移位置滑动到结束位置,使用的是 SlideTransition。Flutter 除了上述的 FadeTransitionSlideTransition 之外,还有如下的常用转场形式:


  • RotationTransition:旋转转场

  • ScaleTransition:缩放转场


既然是这样,我们可以依葫芦画瓢,先用系统其他的转场效果做一个自定义的转场看看。

旋转转场动画

先来看看旋转的转场 RotationTransition,RotationTransition 的构造方法定义如下:


const RotationTransition({    Key? key,    required Animation<double> turns,    this.alignment = Alignment.center,    this.child,  })  : assert(turns != null),        super(key: key, listenable: turns);
复制代码


其中 turns 是动画控制,表示旋转的弧度数,等于动画控制值乘以 2π。alignment 表示旋转围绕的中心位置,默认是居中的。旋转的弧度不要太大,否则动画过快,导致不太好看,经过验证,推荐的起始值 0.2 至 0.3 之间,结束值为 0 表示回到正常位置。起始值如果为负,则是顺时针;如果为正则是逆时针,示例代码如下:


//逆时针围绕中心旋转RouterManager.router.navigateTo(  context,  RouterManager.transitionPath,  transition: TransitionType.custom,  transitionBuilder:      (context, animation, secondaryAnimation, child) {    return RotationTransition(      turns: Tween<double>(        begin: 0.25,        end: 0.0,      ).animate(animation),      child: child,    );  },);
//...//顺时针围绕左下角旋转RouterManager.router.navigateTo( context, RouterManager.transitionPath, transition: TransitionType.custom, transitionBuilder: (context, animation, secondaryAnimation, child) { return RotationTransition( alignment: Alignment.bottomLeft, turns: Tween<double>( begin: -0.25, end: 0.0, ).animate(animation), child: child, ); },);
复制代码


其中 Tween 是系统自带的线性插值方法。

缩放转场动画

缩放转场这类在图片预览会比较常见,一般是从较小的比例缩放到 1:1 比例。使用方式和旋转转场类似,示例代码如下:


RouterManager.router.navigateTo(  context,  RouterManager.transitionPath,  transition: TransitionType.custom,  transitionBuilder:      (context, animation, secondaryAnimation, child) {    return ScaleTransition(      scale: Tween<double>(        begin: 0.5,        end: 1.0,      ).animate(animation),      child: child,    );  },);
复制代码

自定义转场动画

通过阅读源码,其实可以发现RotationTransitionScaleTransition 都是继承自 AnimatedWidget,因此我们可以自己写一个自定义的 Transition 继承自 AnimatedWidget,在 build方法中返回一个 Transform 对象即可。通过这种方式可以做自定义的转场动画效果。我们以变形为例,可以利用 Matrix4skew 方法,在 x 和 y 轴进行变形,就可以得到转场类似卡片变形的效果。也可以只在 X 轴或 Y 轴变形(skewXskewY 方法)。这里以 x,y 轴同时变形定义了一个转场动画:


class SkewTransition extends AnimatedWidget {  const SkewTransition({    Key key,    Animation<double> turns,    this.alignment = Alignment.center,    this.child,  })  : assert(turns != null),        super(key: key, listenable: turns);
Animation<double> get turns => listenable as Animation<double>;
final Alignment alignment;
final Widget child;
@override Widget build(BuildContext context) { final double turnsValue = turns.value; final Matrix4 transform = Matrix4.skew(turnsValue * pi * 2.0, turnsValue * pi * 2.0); return Transform( transform: transform, alignment: alignment, child: child, ); }}
复制代码


使用方式和 RotationTransition 类似:


RouterManager.router.navigateTo(  context,  RouterManager.transitionPath,  transition: TransitionType.custom,  transitionBuilder:      (context, animation, secondaryAnimation, child) {    return SkewTransition(      turns: Tween<double>(        begin: -0.05,        end: 0.0,      ).animate(animation),      child: child,    );  },);
复制代码


实际也可以尝试使用围绕 X 轴旋转,围绕 Y 轴旋转,以及变更中心点位置(alignment)来实现不同的动画转场效果。如果需要更为复杂的动画效果,则可以研究动画的实现,后续篇章将有对应动画的介绍。

运行效果

运行效果如下图所示:


总结

本篇介绍了 fluro 导航到其他页面的自定义转场动画实现,Flutter 本身提供了不少预定义的转场动画,可以通过 transitionBuilder 参数设计多种多样的转场动画,也可以通过自定义的 AnimatedWidget实现个性化的转场动画效果。



发布于: 刚刚阅读数: 2
用户头像

岛上码农

关注

用代码连接孤岛,公众号@岛上码农 2022.03.03 加入

从南漂到北,从北漂到南的业余码农

评论

发布
暂无评论
让页面跳转更有趣 —— 实现自定义页面切换转场动画_flutter_岛上码农_InfoQ写作平台