Flutter 中动画的使用
AnimationController:用于控制 Animation,可以设置动画时长、启动、停止动画。
Listener:用于动画的监听,根据回调,获取动画的当前值,进行渲染。
class _AnimationDemo1State extends State with SingleTickerProviderStateMixin {AnimationController controller;Animation<double> animation;
@overridevoid initState() {super.initState();// 创建 controllercontroller = AnimationController(vsync: this, duration: Duration(milliseconds: 1000));
// 创建 animationanimation = Tween(begin: 50.0, end: 250.0).animate(controller)..addListener(() {// 更新状态 setState(() {});});//在启动动画时,使用 repeat(reverse: true),让动画来回重复执行。controller.repeat(reverse: true);// 监听动画状态。在动画结束时,反向执行;在动画反向执行完毕时,重新启动执行。animation.addStatusListener((status) {if (status == AnimationStatus.completed) {//在动画结束时,反向执行 controller.reverse();} else if (status == AnimationStatus.dismissed) {//在动画反向执行完毕时,重新启动执行 controller.forward();}});// 开始动画 controller.forward();}
@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text("基础动画"),),body: Center(child: Container(width: animation.value,height: animation.value,color: Colors.yellow,),),);}
@overridevoid dispose() {// 停止动画 controller.stop();super.dispose();}}
可以看到 animation 只提供动画数据,因此我们还需要监听动画执行进度,并在回调中使用 setState 强制刷新界面才能看到动画效果。这些步骤都是固定的,有没有什么更简单的方法吗?
AnimatedW
idget 与 AnimatedBuilder
通过这两个 widget 可以简化我们的动画步骤。 AnimatedWidget: 把对动画的监听放到 AnimatedWidget 中,在里面就可以拿到动画的值,进行页面的重绘。
// 通过 AnimatedWidget 来实现动画
class AnimatedWidgetDemo extends AnimatedWidget {AnimatedWidgetDemo({Key key, Animation<double> animation}): super(key: key, listenable: animation);
@overrideWidget build(BuildContext context) {final Animation<double> animation = listenable;return Container(width: animation.value,height: animation.value,color: Colors.red,);}}
class AnimationDemo2 extends StatefulWidget {@overrideState<StatefulWidget> createState() {return _AnimationDemo2State();}}
class _AnimationDemo2State extends State with SingleTickerProviderStateMixin {AnimationController controller;Animation<double> animation;
@overridevoid initState() {super.initState();// 创建 controllercontroller = AnimationController(vsync: this, duration: Duration(milliseconds: 1000));
animation = Tween(begin: 50.0, end: 250.0).animate(controller);
//在启动动画时,使用 repeat(reverse: true),让动画来回重复执行。controller.repeat(reverse: true);// 监听动画状态。在动画结束时,反向执行;在动画反向执行完毕时,重新启动执行。animation.addStatusListener((status) {if (status == AnimationStatus.completed) {//在动画结束时,反向执行 controller.reverse();} else if (status == AnimationStatus.dismissed) {//在动画反向执行完毕时,重新启动执行 controller.forward();}});// 开始动画 controller.forward();}
@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text("AnimatedWidgetDemo"),),body: Center(child: AnimatedWidgetDemo(animation: animation,),),);}
@overridevoid dispose() {controller.stop();super.dispose();}}
AnimatedBuilder: 将动画和渲染逻辑分开。
class _AnimationDemo3State extends State with SingleTickerProviderStateMixin {AnimationController controller;Animation<double> animation;
@overridevoid initState() {super.initState();// 创建 controllercontroller = AnimationController(vsync: this, duration: Duration(milliseconds: 1000));
animation = Tween(begin: 50.0, end: 250.0).animate(controller);
//在启动动画时,使用 repeat(reverse: true),让动画来回重复执行。controller.repeat(reverse: true);// 监听动画状态。在动画结束时,反向执行;在动画反向执行完毕时,重新启动执行。animation.addStatusListener((status) {if (status == AnimationStatus.completed) {//在动画结束时,反向执行 controller.reverse();} else if (status == AnimationStatus.dismissed) {//在动画反向执行完毕时,重新启动执行 controller.forward();}});// 开始动画 controller.forward();}
@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text("AnimatedWidgetDemo"),),body: AnimatedBuilder(animation: animation,builder: (context, child) => Center(child: Container(width: animation.value,height: animation.value,color: Colors.deepPurple,
评论