Flutter 动画之 Explicit 显式动画
- Explicit 显式动画指的是通过手动配置和控制动画过程来实现动画效果的方式,提供对动画状态(比如正向播放、反向播放和重复播放等)的精细化管理,与隐式动画(由 Flutter 自动管理动画过程)相对应
- 显式动画的核心在于使用 AnimationController 和 Animation
- 显式动画可以精细控制,灵活性较高
AnimationController
- AnimationController 继承自 Animation,动画控制器,控制着动画的播放、暂停等状态,管理动画的 duration 持续时间和 vsync(TickerProvider)参数
- 可以监听动画的状态变化(比如如是否完成、是否前进或后退等)
Animation
- Animation 是一个抽象类,代表动画的值随时间的变化,比如通过 Tween#animate 方法绑定到 AnimationController 生成 Animation
- Tween 子类支持颜色、尺寸和区域等多种类型(比如 ColorTween、SizeTween 和 RectTween)
- Tween 定义了动画的 begin 起始值和 end 结束值(比如 0.0 -> 1.0),Tween 补间由系统自动生成中间值
使用 addListener 和 setState 的方式
- 1 初始化动画控制器:在 State 对象的 initState 方法中创建 AnimationController 实例,并指定动画的 duration 持续时间和 vsync(TickerProvider)参数,记得在 dispose 方法中进行释放
- 2 定义动画值的变化范围:使用 Tween 等类定义动画值的起始值和结束值(比如使用 Tween 定义一个从 0.0 到 1.0 的变化范围)
- 3 监听动画值的变化:通过 Animation#addListener 方法添加监听器,在监听器中调用 setState 方法来触发 UI 界面重绘,从而更新界面以反映动画元素的位置、大小等属性的改变
- 4 启动和控制动画:调用 AnimationController 的 forward、reverse 或 repeat 等方法来启动正向播放、反向播放或循环播放
class ExplicitAnimationWidget extends StatefulWidget {
const ExplicitAnimationWidget({super.key});
@override
State<ExplicitAnimationWidget> createState() =>
_ExplicitAnimationWidgetState();
}
class _ExplicitAnimationWidgetState extends State<ExplicitAnimationWidget>
with SingleTickerProviderStateMixin {
late AnimationController _controller;
late Animation<double> _animation;
@override
void initState() {
super.initState();
_controller = AnimationController(
duration: const Duration(seconds: 2),
vsync: this,
);
_animation = Tween<double>(begin: 50.0, end: 200.0).animate(_controller);
_animation.addListener(() {
print('addListener Callback');
setState(() {});
});
_animation.addStatusListener((status) {
if (status == AnimationStatus.completed) {
_controller.reverse();
}
});
_startAnimation();
}
void _startAnimation() {
_controller.forward();
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('显式动画示例'),
),
body: Center(
child: SizedBox(
width: _animation.value,
height: _animation.value,
child: const FlutterLogo(),
),
),
);
}
}
使用 AnimatedWidget 组件
- 其实 AnimatedWidget 内部就是封装 addListener 和 setState 的方式,相当于使用 AnimatedWidget 可以省略监听的逻辑(无需手动调用 addListener 和 setState),将动画逻辑与 UI 组件解耦,方便复用动画
- 1 初始化动画控制器:在 State 对象的 initState 方法中创建 AnimationController 实例,并指定动画的 duration 持续时间和 vsync(TickerProvider)参数,记得在 dispose 方法中进行释放
- 2 定义动画值的变化范围:使用 Tween 等类定义动画值的起始值和结束值(比如使用 Tween 定义一个从 0.0 到 1.0 的变化范围)
- 3 启动和控制动画:调用 AnimationController 的 forward、reverse 或 repeat 等方法来启动正向播放、反向播放或循环播放
class MyAnimatedWidget extends StatefulWidget {
const MyAnimatedWidget({super.key});
@override
State<MyAnimatedWidget> createState() => _MyAnimatedWidgetState();
}
class _MyAnimatedWidgetState extends State<MyAnimatedWidget>
with SingleTickerProviderStateMixin {
late AnimationController _controller;
late Animation<double> _animation;
@override
void initState() {
super.initState();
_controller = AnimationController(
duration: const Duration(seconds: 2),
vsync: this,
);
_animation = Tween<double>(begin: 50.0, end: 200.0).animate(_controller);
_animation.addStatusListener((status) {
if (status == AnimationStatus.completed) {
_controller.reverse();
}
});
_startAnimation();
}
void _startAnimation() {
_controller.forward();
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('AnimatedWidget 示例'),
),
body: Center(
child: CustomAnimatedWidget(animation: _animation),
),
);
}
}
class CustomAnimatedWidget extends AnimatedWidget {
const CustomAnimatedWidget({super.key, required Animation<double> animation})
: super(listenable: animation);
@override
Widget build(BuildContext context) {
final animation = listenable as Animation<double>;
return SizedBox(
width: animation.value,
height: animation.value,
child: const FlutterLogo(),
);
}
}
使用以 Transition 结尾的组件
- 系统内置的显式动画
- 1 初始化动画控制器:在 State 对象的 initState 方法中创建 AnimationController 实例,并指定动画的 duration 持续时间和 vsync(TickerProvider)参数,记得在 dispose 方法中进行释放
- 2 定义动画值的变化范围:使用 Tween 等类定义动画值的起始值和结束值(比如使用 Tween 定义一个从 0.0 到 1.0 的变化范围)
- 3 启动和控制动画:调用 AnimationController 的 forward、reverse 或 repeat 等方法来启动正向播放、反向播放或循环播放
SlideTransition
ScaleTransition
RotationTransition
FadeTransition
class _ScaleTransitionWidgetState extends State<ScaleTransitionWidget>
with SingleTickerProviderStateMixin {
late AnimationController _controller;
late Animation<double> _animation;
@override
void initState() {
super.initState();
_controller = AnimationController(
duration: const Duration(seconds: 2),
vsync: this,
);
_animation = Tween<double>(begin: 0.4, end: 1.0).animate(_controller);
_animation.addStatusListener((status) {
if (status == AnimationStatus.completed) {
_controller.reverse();
}
});
_startAnimation();
}
void _startAnimation() {
_controller.forward();
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('ScaleTransition 示例'),
),
body: Center(
child: ScaleTransition(
scale: _animation,
child: const SizedBox(
width: 100,
height: 100,
child: FlutterLogo(),
),
),
),
);
}
}