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 除了上述的 FadeTransition
、SlideTransition
之外,还有如下的常用转场形式:
-
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,
);
},
);
自定义转场动画
通过阅读源码,其实可以发现RotationTransition
、ScaleTransition
都是继承自 AnimatedWidget
,因此我们可以自己写一个自定义的 Transition
继承自 AnimatedWidget
,在 build
方法中返回一个 Transform
对象即可。通过这种方式可以做自定义的转场动画效果。我们以变形为例,可以利用 Matrix4
的 skew
方法,在 x 和 y 轴进行变形,就可以得到转场类似卡片变形的效果。也可以只在 X 轴或 Y 轴变形(skewX
和 skewY
方法)。这里以 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
实现个性化的转场动画效果。