为了让我们的场景切换更加流畅和一些元素更能抓住用户的眼球,我们在APP中都会添加多种动画来装扮我们的APP,在以往的开发中对于普通的旋转位移,缩放动画我们都有一些简单的处理方式,但是面对复杂的动画我们都会耗费我们大量的时间来进行计算,我们一起来针对Flutter中的动画进行学习,看下在Flutter中我们如何处理我们日常使用的动画。
在Flutter中也为我们提供了多种动画示例,我们稍后看下,我们先看下如何不使用这些动画示例来创建一个我们想要的动画。
我们首先需要一个动画的控制单元,在Flutter中AnimationController来充当这个角色,我们先认识一下AnimationController:
AnimationController({
double value, //给定动画的初始状态
this.duration,//动画执行的时间间隔,如果没有设置reverseDuration则返回时的持续时间也是duration指定的时间
this.reverseDuration,//返回原来状态的动画运行时间
this.debugLabel,//调试的标签
this.lowerBound = 0.0,//动画消失时的值
this.upperBound = 1.0,//动画完成时的值
this.animationBehavior = AnimationBehavior.normal,//如果设置为Normal如果设置的disableAnimations为True则不会浪费时间,如果设置为 AnimationBehavior.preserve则会消耗同样的时间
@required TickerProvider vsync,//防止屏幕外动画,消耗不必要的资源
})
范围控制我们看到在AnimationController为我们提供了0-1的控制,但是在实际使用中很多情况是无法满足我们需求的,我们这时候需要Tween来帮助我们做一个范围的设定,可以设定动画变化的范围。Tween提供了多种样式的变化,如:IntTween,ColorTween,RectTween等变化的范围设定。我们简单来了解下他们,然后可以根据需要在使用的时候进行选择。
IntTween({ int begin, int end }) : super(begin: begin, end: end);//开始的数值,和结束的数值,都是提供的整数
ColorTween({ Color begin, Color end }) : super(begin: begin, end: end);//开始的颜色,和结束的颜色,提供的是颜色值
我们把他们结合起来看可以做些什么:
controller = AnimationController(
duration: Duration(milliseconds: 1000), vsync: this);//创建一个动画的控制器
Tween tween = Tween<double>(begin: 100.0, end: 400.0);//创建一个动画调整大小的限定器
animation = tween.animate(controller);//将限定器与控制器进行绑定,就可以得到一个Animation对象
animation.addListener(() {//当屏幕上每一帧变化的时候都会在这里进行刷新通知,每次刷新都调用我们build方法重绘当前控制的元素
setState(() {});
});
controller.forward();//开始执行动画
如果我们想要监听动画的开始和结束需要给animation添加状态监听:
animation.addStatusListener((status) {
if(status == AnimationStatus.completed){//如果当前状态是已经完成了动画则往下执行
controller.reverse(from:1.0);//将动画反向执行一遍
}
});
有了动画的控制我们只需要根据返回的状态值,控制build里面的元素显示就可以了,比如我们控制Flutter图标的一个放大动画:
@override
Widget build(BuildContext context) {
return Center(
child: Container(
margin: EdgeInsets.symmetric(vertical: 10.0),
height: animation.value,//这里根据返回的限定值进行刷新,将logo显示为指定的大小
width: animation.value,//这里根据返回的限定值进行刷新,将logo显示为指定的大小
child: FlutterLogo(),显示的Flutter图标的组件
),
);
}
其他的动画比如位移和旋转我们可以控制margin和transform的设置,具体的属性设置可以参照之前我们介绍容器时的参数说明。
这样虽然能帮助我们实现动画,如果我们需要重复利用这个动画则需要实现多处,我们这时候可以使用AnimatedWidget来帮助我们做一些简化,Flutter为我们提供了一些AnimatedWidget的示例,比如FadeTransition、PositionedTransition、RelativePositionedTransition、RotationTransition、ScaleTransition、SizeTransition、SlideTransition。这些是已经帮我们做好的了动画模式。我们帮上面的例子通过AnimatedWidget来改造一下。
class ImageAnimationWidget extends AnimatedWidget {//创建一个ImageAnimationWidget继承自AnimatedWidget来实现动画
ImageAnimationWidget({Key key, Animation<double> animation})
: super(key: key, listenable: animation);
@override
Widget build(BuildContext context) {
final Animation<double> animation = listenable;
return Center(
child: Container(
margin: EdgeInsets.symmetric(vertical: 10.0),
height: animation.value,
width: animation.value,
child: FlutterLogo(),
),
);
}
}
这块的代码就是我们刚刚State里的build代码,我们把动画部分提取了出来,这样我们在以后需要多个该动画时直接引用即可,原来的build代码,现在已经被替换为了:
@override
Widget build(BuildContext context) {
return ImageAnimationWidget(animation: animation,);
}
还是上面的例子,如果我们想要使用Flutter为我们提供的示例来实现怎么做呢:
@override
Widget build(BuildContext context) {
return ScaleTransition(scale: animation,child: FlutterLogo(),);
}
就是把State里的build方法替换为了ScaleTransition,然后我们需要修改animation中的Tween的开始结束大小,方便了很多,其他的动画我们可以自己进行实验一下。
通过本篇我们学习了一些简单的动画,Flutter的基础学习也告一段落,接下来需要开一个新的专题,一起学习一个项目的0开始。