flutter动画
1.动画原理:在一段时间内快速的多次改变UI外观,由于人眼会产生视觉暂留所以最终看到的就是一个连续的动画。
UI的一次改变称为一个动画帧,对应一次屏幕刷新。
FPS:帧率,每秒的动画帧数。
flutter动画分为两类:
- 补间动画
- 物理动画
常见动画模式:
- list、grid中的动画:例如一些元素的添加或者删除。
- 转场动画
- 交错动画
基本的动画概念与类:
Animation
是一个抽象类,主要的功能是保存动画的值和状态。常用的一个Animation类是Animation< double >,是一个在一段时间内依次生成一个区间之间的值的类,可以是线性或者曲线或者其他。
可以生成除double之外的其他类型值,如:Animation< Color > 或 Animation< Size >。
AnimationController
是一个动画控制器,控制动画的播放状态,在屏幕刷新的每一帧,就会生成一个新的值。
包含动画的启动forward()、停止stop() 、反向播放 reverse()等方法,在给定的时间段内线性的生成从0.0到1.0(默认区间)的数字。
- 使用Listeners和StatusListeners监听动画状态改变。
AnimationController controller = AnimationController(
duration: Duration(milliseconds: 2000), vsync: this);
Curve
curve:描述动画的曲线过程。
curvedAnimation:指定动画的曲线。
final CurvedAnimation curve =
new CurvedAnimation(parent: controller, curve: Curves.easeIn);
常用Curve:
- linear:匀速的
- decelerate:匀减速
- ease:开始减速后减速
- easeIn:开始慢后快
- easeOut:开始快后慢
- easeInOut:开始慢加速再减速
Tween
继承自Animatable< T >,表示的就是一个 Animation 对象的取值范围,只需要设置开始和结束的边界值(值也支持泛型)。 它唯一的工作就是定义输入范围到输出范围的映射。
例如,Tween可能会生成从红到蓝之间的色值,或者从0到255。
final Tween colorTween =
new ColorTween(begin: Colors.transparent, end: Colors.black54);
Tween.animate:返回一个Animation。
映射过程:
1). Tween.animation通过传入 aniamtionController 获得一个_AnimatedEvaluation 类型的 animation 对象(基类为 Animation), 并且将 aniamtionController 和 Tween 对象传入了 _AnimatedEvaluation 对象。
Animation<T> animate(Animation<double> parent) {
return _AnimatedEvaluation<T>(parent, this);
}
2). animation.value方法即是调用 _evaluatable.evaluate(parent)方法, 而 _evaluatable 和 parent 分别为 Tween 对象和 AnimationController 对象。
T get value => _evaluatable.evaluate(parent);
....
class _AnimatedEvaluation<T> extends Animation<T> with AnimationWithParentMixin<double> {
_AnimatedEvaluation(this.parent, this._evaluatable);
3). 这里的 animation 其实就是前面的 AnimationController 对象, transform 方法里面的 animation.value则就是 AnimationController 线性生成的 0.0~1.0 直接的值。 在 lerp 方法里面我们可以看到这个 0.0~1.0 的值被映射到了 begin 和 end 范围内了。
T evaluate(Animation<double> animation) => transform(animation.value);
T transform(double t) {
if (t == 0.0)
return begin;
if (t == 1.0)
return end;
return lerp(t);
}
T lerp(double t) {
assert(begin != null);
assert(end != null);
return begin + (end - begin) * t;
}
vsync
接收一个TickerProvider类型的对象,它的主要职责是创建Ticker。
防止屏幕外动画消耗资源。
流程图:
[图片上传失败...(image-115b94-1636441483468)]
总结:
过程:
- TickerProvider 会创建一个 Ticker, 并将_tick(TickerCallback 类型)回调方法绑定到了 这个 Ticker, 这样 AnimationController 就将回调方法 _tick 和 Ticker 绑定了。
- Ticker 会在 start 函数内将_tick 被绑定到 SchedulerBinding 的帧回调方法内。
- SchedulerBinding 则是在构造方法中将自己的 _handleBeginFrame 函数和 window 的 onBeginFrame 绑定了回调。 这个回调会在屏幕需要准备显示帧之前回调。
- 在 AnimationController 的回调当中, 计算当前的的_value 值, 更新 Animation Status 的状态, 判断是否动画已经结束。 最后通过 notifyListeners 和_checkStatusChanged 方法通知给监听器 value 和 AnimationStatus 的变化。
回调:
ui.window.onBeginFrame = handleBeginFrame;
ui.window.onDrawFrame = handleDrawFrame;
- window调用SchedulerBinding的_handleBeginFrame方法
- SchedulerBinding调用Ticker的_tick方法
- Ticker调用 AnimationController的_tick的方法,
- animationContoller通知监听器
- 而监听器调用widget的setStatus方法来调用build更新
- build使用了Animation对象当前的值来绘制动画帧
用AnimatedWidget简化
不使用addListener()和setState()来给widget添加动画。
使用AnimatedWidget,将widget分离出来,创建一个可重用动画的widget,AnimatedWidget中会自动调用addListener()和setState()
class AnimatedImage extends AnimatedWidget {
AnimatedImage({Key key, Animation<double> animation})
: super(key: key, listenable: animation);
Widget build(BuildContext context) {
final Animation<double> animation = listenable;
return new Center(
child: Image.asset("imgs/avatar.png",
width: animation.value,
height: animation.value
),
);
}
}
常用控件
AnimatedModalBarrier、DecoratedBoxTransition、FadeTransition、PositionedTransition、RelativePositionedTransition、RotationTransition、ScaleTransition、SizeTransition、SlideTransition
AnimatedBuilder重构
如何渲染过渡,把渲染过程也抽象出来:
AnimatedBuilder的示例包括: BottomSheet、 PopupMenu、ProgressIndicator、RefreshIndicator、Scaffold、SnackBar、TabBar。
转场动画
MaterialPageRoute:平台风格一致的路由切换动画
CupertinoPageRoute:左右切换风格
Navigator.push(context, CupertinoPageRoute(
builder: (context)=>PageB(),
));
自定义:PageRouteBuilder
交织动画
1.要创建交织动画,需要使用多个动画对象(Animation)。
2.一个AnimationController控制所有的动画对象。
3.给每一个动画对象指定时间间隔(Interval)
AnimatedSwitcher
可以同时对其新、旧子元素添加显示、隐藏动画.
当AnimatedSwitcher的child发生变化时(类型或Key不同),旧child会执行隐藏动画,新child会执行执行显示动画。
希望大家支持一下,感谢
https://itunes.apple.com/cn/app/id1581903089
网友评论