一、如何为动画添加监听器?
有时我们需要制动动画执行的进度和状态,在Flutter中我们可以通过Animation的addListener与addStatusListener方法为动画添加监听器:
-addListener:动画的值发生变化时被调用
-addStatusListener:动画状态发生变化时被调用
二、用AnimatedWidget与AnimatedBuilder简化和重构我们对动画的使用
1、什么是AnimatedWidget?
我们可以将AnimatedWidget理解为Animation的助手,使用它可以简化我们对动画的使用,在为widget添加动画的学习中我们不难发现,在不适用AnimatedWidget的情况下需要手动调用动画的addListener()并在回调中添加setState才能看到动画效果,AnimatedWidget将为我们简化这一操作。
在下面的重构示例中,LogoApp现在继承自AnimatedWidget而不是StatefulWidget.
AnimatedWidget在绘制时使用动画的当前值。LogoApp仍然管理着AnimationController和Tween。
代码:
import 'package:flutter/material.dart';
import 'package:flutter_color_plugin/flutter_color_plugin.dart';
void main() => runApp(AnimationUse());
class AnimationUse extends StatefulWidget {
@override
_AnimationPageState createState() => _AnimationPageState();
}
class AnimatedLogo extends AnimatedWidget{
AnimatedLogo({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),
height: animation.value,
width: animation.value,
child: FlutterLogo(),
),
);
}
}
class _AnimationPageState extends State<AnimationUse>
with SingleTickerProviderStateMixin {
Animation<double> animation;
AnimationController controller;
@override
void initState() {
super.initState();
//vsync:在动画不可用的时候做一些回收
controller =
new AnimationController(vsync: this, duration: Duration(seconds: 2));
animation = Tween<double>(begin: 0, end: 300).animate(controller);
controller.forward();
}
@override
void dispose() {
//回收动画
controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return AnimatedLogo(animation: animation);
}
}
//class _AnimationPageState extends State<AnimationUse>
// with SingleTickerProviderStateMixin {
// Animation<double> animation;
// AnimationController controller;
// AnimationStatus animationStatus;
// double animationValue;
//
// @override
// void initState() {
// super.initState();
// //vsync:在动画不可用的时候做一些回收
// controller =
// new AnimationController(vsync: this, duration: Duration(seconds: 2));
// animation = Tween<double>(begin: 0, end: 300).animate(controller)
// //..两个点表示animation的返回值,与animation.addListener()效果是等价的
// ..addListener(() {
// //补间动画是从0变化到300的,执行过程中可以通过animation.value获取到动画的值
// setState(() {
// animationValue = animation.value;
// });
// })
// ..addStatusListener((AnimationStatus state) {
// setState(() {
// animationStatus = state;
// });
// });
// }
//
// @override
// void dispose() {
// //回收动画
// controller.dispose();
// super.dispose();
// }
//
// @override
// Widget build(BuildContext context) {
// TextStyle textStyle = TextStyle(fontSize: 20);
// return Container(
// margin: EdgeInsets.only(top: 30),
// decoration: BoxDecoration(color: Colors.white),
// child: Column(
// children: <Widget>[
// GestureDetector(
// onTap: () {
// controller.reset();
// controller.forward();
// },
// child: Text(
// 'Start',
// textDirection: TextDirection.ltr,
// ),
// ),
// Text('State:' + animationStatus.toString(),
// textDirection: TextDirection.ltr, style: textStyle),
// Text('Value:' + animationValue.toString(),
// textDirection: TextDirection.ltr, style: textStyle),
// Container(
// height: animation.value,
// width: animation.value,
// child: FlutterLogo(),
// )
// ],
// ),
// );
//
// return Container(
// width: 200,
// height: 300,
// child: FlutterLogo(),
// );
// }
//}
运行结果:
三、实现步骤:
1、AnimatedLogo 继承自AnimatedWidget,AnimatedWidget会根据它的值重新调用builded(),也就是说build会根据它的值来重新渲染所以才会立即看到动画的效果
2、在state类里面初始化controller以及animation,然后在初始化的时候调用forward()来播放动画
通过继承AnimatedWidget构建出它的子类,然后就可以像使用普通widget一样使用它。