一.图片放大示例
要点:
- AnimationController,用于设定动画的执行时间,以及动画的开启、反转等动作。
controller = new AnimationController(duration: const Duration(seconds: 4), vsync: this); - Animation,用于设定动画取值范围,并可增加动画监听,addListener是帧监听,每一帧都会回调。
animation = new Tween(begin: 100.0, end: 300.0).animate(controller)
..addListener(() {
// 通过setState实现重绘
setState(() => {});
}); - controller.forward() // 启动动画
- controller.dispose() // 释放动画资源

class _MyHomePageState extends State<MyHomePage>
with SingleTickerProviderStateMixin {
AnimationController controller;
Animation<double> animation;
initState() {
super.initState();
// 设定动画执行时间
controller = new AnimationController(
duration: const Duration(seconds: 4), vsync: this);
//图片宽高从100变到300
animation = new Tween(begin: 100.0, end: 300.0).animate(controller)
..addListener(() {
// 通过setState实现重绘
setState(() => {});
});
//启动动画
controller.forward();
}
@override
Widget build(BuildContext context) {
return new Center(
child: Image.asset("images/avatar.jpg",
width: animation.value, height: animation.value),
);
}
dispose() {
//释放动画资源
controller.dispose();
super.dispose();
}
}
二.取值变化曲线
变化的取值,从begin到end,默认是线性变化的。变化过程可以设定曲线函数,如:
- animation=CurvedAnimation(parent: controller, curve: Curves.bounceIn);
Curves 变化曲线,有很多种:
- linear 线性
- bounceIn 弹性
- ease 开始快后来慢
- easeIn 开始慢后来快
- 。。。。。。
class _MyHomePageState extends State<MyHomePage>
with SingleTickerProviderStateMixin {
AnimationController controller;
Animation<double> animation;
initState() {
super.initState();
// 设定动画执行时间
controller = new AnimationController(
duration: const Duration(seconds: 3), vsync: this);
// 值变化曲线
animation=CurvedAnimation(parent: controller, curve: Curves.bounceIn);
//图片宽高从100变到300
animation = new Tween(begin: 100.0, end: 400.0).animate(animation)
..addListener(() {
// 通过setState实现重绘
setState(() => {});
});
//启动动画
controller.forward();
}
@override
Widget build(BuildContext context) {
return new Center(
child: Image.asset("images/avatar.jpg",
width: animation.value, height: animation.value),
);
}
dispose() {
//释放动画资源
controller.dispose();
super.dispose();
}
}
三.AnimatedWidget
上面使用addListener和setState实现重绘,AnimatedWidget则简化了这个操作。继承AnimatedWidget后,可以直接使用animation的值。
class AnimatedImage extends AnimatedWidget {
AnimatedImage({Key key, Animation<double> animation})
: super(key: key, listenable: animation);
Widget build(BuildContext context) {
final Animation<double> animation = listenable;
return new Center(
child: Image.asset("images/avatar.jpg",
width: animation.value,
height: animation.value
),
);
}
}
class _MyHomePageState extends State<MyHomePage>
with SingleTickerProviderStateMixin {
AnimationController controller;
Animation<double> animation;
initState() {
super.initState();
// 设定动画执行时间
controller = new AnimationController(
duration: const Duration(seconds: 3), vsync: this);
// 值变化曲线
animation=CurvedAnimation(parent: controller, curve: Curves.bounceIn);
//图片宽高从100变到300
animation = new Tween(begin: 100.0, end: 400.0).animate(animation);
//启动动画
controller.forward();
}
@override
Widget build(BuildContext context) {
return AnimatedImage(animation: animation,);
}
dispose() {
//释放动画资源
controller.dispose();
super.dispose();
}
}
四. AnimatedBuilder
构造方法:
const AnimatedBuilder({
Key key,
@required Listenable animation,
@required this.builder,
this.child,
})
- animation 定义的动画
- child 作用的目标,也就是要给哪个widget添加动画
- build 封装了绘制过程
class _MyHomePageState extends State<MyHomePage>
with SingleTickerProviderStateMixin {
AnimationController controller;
Animation<double> animation;
initState() {
super.initState();
// 设定动画执行时间
controller = new AnimationController(
duration: const Duration(seconds: 3), vsync: this);
// 值变化曲线
animation = CurvedAnimation(parent: controller, curve: Curves.bounceIn);
//图片宽高从100变到300
animation = new Tween(begin: 100.0, end: 400.0).animate(animation);
//启动动画
controller.forward();
}
@override
Widget build(BuildContext context) {
return AnimatedBuilder(
animation: animation,
child: Image.asset("images/avatar.jpg"),
builder: (BuildContext context, Widget child) {
return new Center(
child: Container(
height: animation.value,
width: animation.value,
child: child,
),
);
},
);
}
dispose() {
//释放动画资源
controller.dispose();
super.dispose();
}
}
五.封装动画
将动画与目标分离开,制定动画过程,传入目标child widget。
class GrowTransition extends StatelessWidget {
GrowTransition({this.child, this.animation});// 传入目标和动画设定
final Widget child;
final Animation<double> animation;
// 对目标child设置动画执行过程
Widget build(BuildContext context) {
return new Center(
child: new AnimatedBuilder(
animation: animation,
builder: (BuildContext context, Widget child) {
return new Container(
height: animation.value,
width: animation.value,
child: child
);
},
child: child
),
);
}
}
class _MyHomePageState extends State<MyHomePage>
with SingleTickerProviderStateMixin {
AnimationController controller;
Animation<double> animation;
initState() {
super.initState();
// 设定动画执行时间
controller = new AnimationController(
duration: const Duration(seconds: 3), vsync: this);
// 值变化曲线
animation = CurvedAnimation(parent: controller, curve: Curves.bounceIn);
//图片宽高从100变到300
animation = new Tween(begin: 100.0, end: 400.0).animate(animation);
//启动动画
controller.forward();
}
@override
Widget build(BuildContext context) {
return GrowTransition(
animation: animation,
child: Image.asset("images/avatar.jpg"),
);
}
dispose() {
//释放动画资源
controller.dispose();
super.dispose();
}
}
六.状态监听器
- addListener 是每一帧的监听回调
- addStatusListener 监听的是动画过程的状态,包括:
- dismissed 动画停止
- forward 动画开始正向执行
- reverse 动画开始反向执行
- completed 动画执行完毕
class _MyHomePageState extends State<MyHomePage>
with SingleTickerProviderStateMixin {
AnimationController controller;
Animation<double> animation;
initState() {
super.initState();
// 设定动画执行时间
controller = new AnimationController(
duration: const Duration(seconds: 3), vsync: this);
// 值变化曲线
animation = CurvedAnimation(parent: controller, curve: Curves.bounceIn);
//图片宽高从100变到300
animation = new Tween(begin: 100.0, end: 400.0).animate(animation);
// 添加状态监听
animation.addStatusListener((status) {
if (status == AnimationStatus.completed) {
//动画执行结束时反向执行动画
controller.reverse();
} else if (status == AnimationStatus.dismissed) {
//动画恢复到初始状态时执行动画(正向)
controller.forward();
}
});
//启动动画
controller.forward();
}
@override
Widget build(BuildContext context) {
return GrowTransition(
animation: animation,
child: Image.asset("images/avatar.jpg"),
);
}
dispose() {
//释放动画资源
controller.dispose();
super.dispose();
}
}
欢迎关注我的公众号:Flutter和Dart开发实践
让我们共同学习进步,It is never too late to learn!

网友评论