Animation
Animation是一个抽象类,本身和UI渲染无关,只负责保存动画的插值和状态,widget可以在build函数中读取Animation对象的当前值。Animation对象是一个在一段时间内依次生成一个区间(Tween)之间值的类。Animation对象的输出可以是线性、曲线、一个步进函数或任何其他可以设计的映射,这由Curve决定。
Curve
Curve定义常用动画曲线的数组,描述动画过程(动画效果可点击跳转链接),可以通过CurveAnimation指定动画的曲线。以下为常用:
Curve曲线 | 动画过程 |
Iinear | 匀速 |
decelerate | 匀减速 |
ease | 开始加速,后面减速 |
easeIn | 开始慢后面快 |
eaSEOut | 开始快后面慢 |
easeInOut | 开始慢,然后加速,最后减速 |
AnimationController
AnimationController用于控制动画,动画的启动forward()、停止stop()、反向播放 reverse()等方法。它会在动画的每一帧生成一个新的值。默认情况下AnimationController对象值的默认范围[0.0,1.0],AnimationController派生自Animation<double>,因此可以在需要Animation对象的任何地方使用。
Ticker
当创建AnimationController时 ,需要传递一个vsync参数,它接收一个TickerProvider类型的对象,主要职责是创建Ticker。Flutter应用在启动时都会绑定一个SchedulerBiSnding,通过ScheduerlBinding可以给每一次屏幕刷新添加回调,而Ticker就是通过SchedulerBinding来添加屏幕刷新回调,这样一来每次屏幕刷新都会调用TickerCallback。使用Ticker来驱动动画会防止屏幕外动画(动画的ui不在当前屏幕时,如锁屏)消耗不必要的资源,因为Flutter中屏幕刷新时会通知到绑定的SchedulerBinding,而TIcker是受SchedulerBinding驱动的,由于锁屏后屏幕会停止刷新,所以Ticker就不会触发。
abstract class TickerProvider {
/// Abstract const constructor. This constructor enables subclasses to provide
/// const constructors so that they can be used in const expressions.
const TickerProvider();
/// 通过一个回调 创建 Ticker
///
/// The kind of ticker provided depends on the kind of ticker provider.
Ticker createTicker(TickerCallback onTick);
}
注意:通常我们会将SingleTickerProviderStateMixin
添加到State
的定义中,然后将State对象作为vsync
的值
Tween
为了弥补AnimationController数据的局限性,可以使用Tween来添加映射以生成不同的范围或数据类型的值,Tween是一个无状态(stateless)对象,他的唯一职责就是定义从输入范围到输出范围的映射。
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: "Animation demo",
home: AnimWidget(),
);
}
}
class AnimWidget extends StatefulWidget {
@override
State<StatefulWidget> createState() => _AnimWidgetState();
}
class _AnimWidgetState extends State<AnimWidget> with TickerProviderStateMixin {
AnimationController _controller;
Animation<double> _animation;//基本动画
Animation<double> _curveAnmiation;//设置curve
Animation<double> _shakeCurveAnmiation;//自定义curve
@override
void initState() {
super.initState();
_controller = new AnimationController(
duration: const Duration(seconds: 5), vsync: this);
_animation = new Tween(begin: 0.0, end: 100.0).animate(_controller)
..addListener(() {
setState(() {});
});
_curveAnmiation = new Tween(begin: 0.0, end: 100.0)
.animate(CurvedAnimation(parent: _controller, curve: Curves.easeInOut))
..addListener(() {
setState(() {});
});
_shakeCurveAnmiation = new Tween(begin: 0.0, end: 100.0)
.chain(CurveTween(curve: ShakeCurve()))
.animate(_controller)
..addListener(() {
setState(() {});
});
_controller.forward();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: <Widget>[
Image.asset(
ImageHelper.wrapAssets('splash_Flutter.png'),
width: _animation.value,
height: _animation.value,
),
Image.asset(
ImageHelper.wrapAssets('splash_Flutter.png'),
width: _curveAnmiation.value,
height: _curveAnmiation.value,
),
Image.asset(
ImageHelper.wrapAssets('splash_Flutter.png'),
width: _shakeCurveAnmiation.value,
height: _shakeCurveAnmiation.value,
)
],
),
);
}
@override
void dispose() {
super.dispose();
_controller.dispose();
}
}
class ShakeCurve extends Curve {
@override
double transform(double t) {
return t;
}
}