我的博客
本章再练习几个隐式和显式动画, 并且集合二个或多个Animation对象完成交织动画。
首先来看AnimatedContainer
AnimatedContainer
基本上看过Flutter官方动画教程的, 都看过关于AnimatedContainer的示例, 我们也来做一个。 AnimatedContainer是一个隐式动画对象, 无需设置AnimationController来手动控制动画的启动与停止, 只需要设计数值的起始和终值。
AnimatedContainer, 从名字看, 是将常用的Container组件进行了动画处理, 实际也确实如此。 原来Container的大部分参数都可以设置动画数值。 同时还增加了一个非常好的控制方法onEnd:(){}
, 方便在收到动画结束信息后, 可以切换其它操作。
import 'package:flutter/material.dart';
class MyAnimatedContainerDemo extends StatefulWidget {
@override
_MyAnimatedContainerDemoState createState() =>
_MyAnimatedContainerDemoState();
}
class _MyAnimatedContainerDemoState extends State
with SingleTickerProviderStateMixin {
bool isActive = false;
final Duration duration = Duration(milliseconds: 2000);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('点击缩放-AnimatedContainer组件')),
body: Center(
child: AnimatedContainer(
duration: duration,
width: isActive ? 200 : 100,
height: isActive ? 200 : 100,
decoration: BoxDecoration(
color: isActive ? Colors.red : Colors.blue,
borderRadius: BorderRadius.circular(isActive ? 20 : 0)),
onEnd: () {
setState(() {
isActive = !isActive;
});
},
child: InkWell(
onTap: () {
setState(() {
isActive = !isActive;
});
},
child: CircleAvatar(
backgroundImage: AssetImage('assets/images/head.jpg'),
),
),
),
),
);
}
}
效果如下:
从代码中可以看到, 我们对AnimatedContainer的width, height, color和borderRadius都进行了设置, 并且在动画结束(onEnd)的时候, 对数值进行了反转, 因此带动动画也Reverse了。
RotationTransition
RotationTransition是一个旋转组件, 其child默认围绕中心旋转。 RotationTransition的参数turns是一个Animation
对象, 用于更新当前旋转的角度。看示例。
import 'package:flutter/material.dart';
class MyRotationTransitionDemo extends StatefulWidget {
@override
_MyRotationTransitionDemoState createState() =>
_MyRotationTransitionDemoState();
}
class _MyRotationTransitionDemoState extends State
with SingleTickerProviderStateMixin {
AnimationController controller;
Animation turns;
Duration duration = Duration(milliseconds: 3000);
@override
void initState() {
super.initState();
controller = AnimationController(vsync: this, duration: duration);
turns = Tween(begin: 0.0, end: 1.0).animate(controller);
controller.repeat();
}
@override
void dispose() {
controller?.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('RotationTransition组件')),
body: Center(
child: RotationTransition(
turns: turns,
child: Container(
width: 200,
height: 200,
padding: EdgeInsets.all(5.0),
decoration: BoxDecoration(
shape: BoxShape.circle,
border: Border.all(color: Colors.blue),
),
child: CircleAvatar(
backgroundImage: AssetImage('assets/images/head.jpg'),
),
),
),
),
);
}
}
效果如下:
复杂交织(组合)动画
现在我们来做一个比较复杂的交织(组合)动画。 先放效果图。
从图中可以看到,
- 外部圈内的颜色周期性变化
- 头像周期性的缩小、放大
- 头像周期性的旋转
其实这是一个比较简单的交织(组合)动画, 只是简单的将AnimatedContainer、ScaleTransition和RotationTransition进行了组合而已, 三者没有关联, 各自负责自己的动画。
来看代码。
import 'dart:async';
import 'package:flutter/material.dart';
class MyComplexAnimationDemo extends StatefulWidget {
@override
_MyComplexAnimationDemoState createState() => _MyComplexAnimationDemoState();
}
class _MyComplexAnimationDemoState extends State
with TickerProviderStateMixin {
// 控制AnimatedContainer的动画
Timer timer;
bool isActive = true;
// 控制widget缩放scale
AnimationController scaleController;
Animation scale;
// 控制widget旋转rotation
AnimationController rotationController;
Animation turns;
Duration duration = Duration(milliseconds: 1000);
@override
void initState() {
super.initState();
// 定时让AnimatedContainer的参数做变动
timer = Timer.periodic(duration, (t) {
setState(() {
isActive = !isActive;
});
});
// 设置缩放控制器和数值区间
scaleController = AnimationController(vsync: this, duration: duration);
scale = Tween(begin: 0.8, end: 1.0).animate(scaleController);
scaleController.repeat(reverse: true);
// 设置旋转控制器和数值区间, 旋转速度慢一点(持续时间长一点), 不做状态监听, 让动画一直重复就好
rotationController =
AnimationController(vsync: this, duration: duration * 8);
turns = Tween(begin: 1.0, end: 0.0).animate(rotationController);
rotationController.repeat();
}
@override
void dispose() {
timer?.cancel();
timer = null;
scaleController?.dispose();
rotationController?.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('复杂交织动画')),
body: Center(
child: AnimatedContainer(
width: 200,
height: 200,
padding: EdgeInsets.all(10),
duration: duration,
decoration: BoxDecoration(
color: isActive ? Colors.blue : Colors.grey,
shape: BoxShape.circle,
),
child: ScaleTransition(
scale: scale,
child: RotationTransition(
turns: turns,
child: CircleAvatar(
backgroundImage: AssetImage('assets/images/head.jpg'),
),
),
),
),
),
);
}
}
好吧, 文章已经够长了, 后面抽空再写一篇带顺序关系的动画。