Flutter中动画的核心类库是Animation,它并不是一个widget,Animation是一个抽象类,就相当于一个定时器,用来描述当前动画的开始,暂停,以及数值状态,与ui渲染没有任何关系,它不能直接控制ui页面上的组件的样式,组件只能通过获取它的状态来改变ui的状态。
AnimationController
介绍
AnimationController是动画的控制器,用来管理动画。 在AnimationController的构造方法中定义了如下主要参数:
duration
:动画持续的时间lowerBound
:动画最小值,默认值0upperBound
:动画最大值,默认值1vsync
:为动画添加一个屏幕刷新的回调,每次屏幕刷新都会调用TickerCallback,目的是使用Ticker
来驱动动画会防止屏幕外动画(动画的UI不在当前屏幕时,如锁屏时)消耗不必要的资源。因为Flutter中屏幕刷新时会通知Ticker,锁屏后屏幕会停止刷新,所以Ticker就不会再触发。最简单的做法是将SingleTickerProviderStateMixin
添加到State的定义中。
使用
如下所示,声明一个AnimationController控制器对象,初始化中指定动画时长为5秒,不改变默认的最大最小值。为这个控制器添加listener监听,每次控制器的value发生改变时监听中都会收到回调。前面说Animation不负责ui的变化,所以这里要在监听中调用setState
方法使得ui可以响应到控制器的数值变化。
代码
代码语言:javascript复制class _AnimationPageState extends State<AnimationPage> with SingleTickerProviderStateMixin{
AnimationController _animationController;
@override
void initState() {
// TODO: implement initState
super.initState();
_animationController = AnimationController(duration:Duration(seconds: 5),vsync: this);
_animationController.addListener(() {
setState(() {
});
});
_animationController.forward();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("动画"),),
body: Center(
child: Container(
color: Colors.red,
width: _animationController.value * 100,
height: _animationController.value * 100,
),
),
);
}
}
复制代码
效果
Tween
上面说使用AnimationController
可以控制ui控件尺寸的变化,但是如果要是想让颜色等属性也发生变化应该如何实现呢?Flutter中提供了Tween
对象来实现补间动画。 Tween类中提供了两个泛型参数begin
和end
,也就是你可以指定你要进行变化的属性值,比如有很多Flutter中已经封装好的继承自Tween的补间动画类:ColorTween
,SizeTween
,BorderTween
。当然如果想自定义的话,继承Tween实现lerp
方法即可,该方法用来描述你想在动画时间内如何改变你所指定的属性值。 下面是直接使用ColorTween的一个例子,初始化tween后通过animate
方法可以得到Animation对象,就可以在控件中通过获取Animation对象的value来不停地改变控件的属性,从而实现了一个控件由红到绿的变化。
代码
代码语言:javascript复制class _AnimationPageState extends State<AnimationPage> with SingleTickerProviderStateMixin{
AnimationController _animationController;
ColorTween _tween;
Animation<Color> _animation;
@override
void initState() {
// TODO: implement initState
super.initState();
_animationController = AnimationController(duration:Duration(seconds: 5),vsync: this);
_tween = ColorTween(begin: Colors.red,end: Colors.green);
_animationController.addListener(() {
setState(() {
});
});
_animation = _tween.animate(_animationController);
_animationController.forward();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("动画"),),
body: Center(
child: Container(
color: _animation.value,
width: 300,
height: 300,
),
),
);
}
}
复制代码
效果
循环动画实现心跳效果
在一些情况的需求场景下,我们并不只是希望动画只执行一次,而是需要重复的进行循环动画,如下图实现一个心跳效果:
其实代码很简单,动画控制器中提供了一个addStatusListener
方法来监听动画状态的变化,这里一共有4状态:
forward
:动画开始正向执行reverse
:动画开始反向执行completed
:动画正向执行结束dismissed
:动画反向执行结束
根据这一方法,可以在监听中通过判断动画状态不断的正向、反向重复执行动画从而达到循环效果:
代码语言:javascript复制_animationController.addStatusListener((status) {
if(_animationController.isCompleted){
// 正向结束
_animationController.reverse();
}else if(_animationController.isDismissed){
// 反向结束
_animationController.forward();
}
});
复制代码
CurvedAnimation
上面说的都是线性的动画效果,CurvedAnimation则可以将动画过程定义为一个非线性曲线。AnimationController一样都是继承自Animation。Flutter中封装好了很多个曲线动画效果的Curve,开发者也可以自定义Curve效果。这里是一个bounceIn
的例子:
_animationController = AnimationController(
lowerBound: 0,
upperBound: 1,
duration: Duration(milliseconds: 800),
vsync: this);
_animationController.addListener(() {
setState(() {});
});
_curvedAnimation =
CurvedAnimation(parent: _animationController, curve: Curves.bounceIn);
复制代码
代码语言:javascript复制Image.asset(
"assets/image/heart.png",
width: _curvedAnimation.value * 300,
height: _curvedAnimation.value * 300,
)
复制代码
以上就是Flutter动画的简单实用,如有错误,还望指出