Flutter开发指南:如何同步动画路径?
简介
flutter中有一个自定义的Route组件,叫做MaterialPageRoute。正常情况下,如果我们跳转到flutter,需要将MaterialPageRoute发送给Navigator。
但是MaterialPageRoute太常见了。如果我们想再做一次跳跃结果怎么办?
让我们看看。
使用自定义跳转
一般情况下,我们需要使用Navigator和MaterialPageRoute进行路线跳转,如下图:
Navigator.push(context, MaterialPageRoute(builder: (context) { return const NextPage();
如果要应用自定义动画,需要修复道路。
在flutter中,需要使用PageRouteBuilder来构建路由。
我们先看一下PageRouteBuilder的定义:
class PageRouteBuilder<T> extends PageRoute<T> { PageRouteBuilder({ super.settings, required this.pageBuilder, this.transitionsBuilder = _defaultTransitionsBuilder, this.transitionDuration = const Duration(milliseconds: 300), this.reverseTransitionDuration = const Duration(milliseconds: 300), this.opaque = true, this.barrierDismissible = false, this.barrierColor, this.barrierLabel, this.maintainState = true, super.fullscreenDialog, })
PageRouteBuilder也是PageRoute的一种类型。在构建PageRouteBuilder时,通过控制不同的属性值,可以自由控制pageBuilder、transitionsBuilder、transitionDuration、reverseTransitionDuration等功能。
可以看到自由度还是很高的。
pageBuilder 是输入路线的页面。它必须被定义,否则路径将毫无意义。
此外,可以使用transitionsBuilder设置过渡效果。
这里的RouteTransitionsBuilder是一个返回Widget的Function:
typedef RouteTransitionsBuilder = Widget Function(BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation, Widget child);
所以理论上我们可以返回任何Widget,但一般情况下我们会返回一个AnimatedWidget,它代表动画效果。
flutter动画的基本方法
有一个flutter专用的动画包,名为flutter/animation.dart。 flutter 中所有动画的基础称为动画。
Animation 定义了多个监听器来跟踪动画的变化,同时还提供了一个 AnimationStatus 来存储当前的动画状态:
abstract class Animation<T> extends Listenable implements ValueListenable<T> { const Animation(); AnimationWithParentMixin<T> @override void addListener(VoidCallback listener); @override void removeListener(VoidCallback listener); void addStatusListener(AnimationStatusListener listener); void removeStatusListener(AnimationStatusListener listener); AnimationStatus get status;
AnimationStatus 是一个枚举类,包含了各种动画状态。now:
enum AnimationStatus { dismissed, forward, reverse, completed, }
表示动画正在执行一开始就停顿了。
前进表示从头到尾播放动画。
反向表示动画从结尾播放到开头。
finished 表示游戏结束,动画到最后停止。
拿到动画后,如何控制动画呢?这里需要AnimationController。
AnimationController 可以控制动画时长。动画的下限值 lowerBound 变为 0.0,动画的上限值 upperBound 变为 1.0,依此类推。如果你想设置不同的Bound值,你可以尝试配置Animatable。如果你希望动画过渡是非线性的,可以尝试继承Animation。应用您自己的调整曲线。
应用自定义路径
这个在 flutter 上使用 SlideTransition。 SlideTransition 是一个 AnimatedWidget,它显示元素位置变化的动画。
class SlideTransition extends AnimatedWidget { const SlideTransition({ super.key, required Animation<Offset> position, this.transformHitTests = true, this.textDirection, this.child, }) : assert(position != null), super(listenable: position);
查看它的构造函数,可以发现SlideTransition需要一个position属性。这个位置是一个Animation对象,它包含一个Offset。
那时候,这个地方是值得听的。通过控制Offset的变化,可以调整相应的widget来得到动画效果。
Offset 是表示位置的类。 (0,0) 表示该小部件的左顶点位于屏幕的左上角。同样,(1,1) 表示该小部件的左顶点位于屏幕的右下角。
由于路径后面有一个新页面,我们想要一个将页面从右下角移动到左上角的动画,我们可以这样做:
Route customRoute() { return PageRouteBuilder( pageBuilder: (context, animation, secondaryAnimation) => const SecondPage(), transitionsBuilder: (context, animation, secondaryAnimation, child) { const begin = Offset(1.0, 1.0); const end = Offset.zero; const curve = Curves.easeOut; var tween = Tween(begin: begin, end: end).chain(CurveTween(curve: curve)); return SlideTransition( position: animation.drive(tween), child: child, ); }, ); }
这里的开始和结束表示小部件已从屏幕右下角移动到屏幕左上角。
Tween 表示起始值和结束值之间的线性过渡,这是一个动态过程。此外,还可以对变化曲线进行插值。这里使用了CurveTween,并且选择了Curves.easeOut曲线类型。
最后调用animation.drive方法将Tween连接到Animation上,这样动画就完成了。
总结
程序运行最终结果如下:
其实flutter动画很简单。请记住,小部件位置在不同的曲线上会发生变化。
本文示例:https://github.com/ddean2009/learn-flutter.git
版权声明
本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。