AnimatedWidget
用于简化动画管理逻辑的组件
AnimatedWidget是Flutter中的一个核心动画组件,主要用于简化动画管理逻辑。它通过将动画监听器(AnimationListener)与Widget构建过程封装在一起,实现自动响应动画值变化并重建UI。其核心逻辑
基于Flutter的动画系统(Animation对象),当动画值更新时,AnimatedWidget自动调用build方法重绘子组件,无需开发者手动管理setState。
使用场景:
- 简化动画代码: 适用于需要根据动画值(如透明度、位置、尺寸)动态更新UI的场景,避免重复编写
addListener和setState。 - 与
AnimationController配合: 常与AnimationController、Tween等动画类结合,用于补间动画(如渐变、平移)。 - 性能优化: 通过隔离动画逻辑,减少不必要的全局重建,提升动画流畅性。
示例
基础透明度动画
import 'package:flutter/material.dart';
class FadeInWidget extends AnimatedWidget {
const FadeInWidget({
Key? key,
required Animation<double> animation,
}) : super(key: key, listenable: animation);
Widget build(BuildContext context) {
final animation = listenable as Animation<double>;
return Opacity(
opacity: animation.value, // 透明度从 0 到 1
child: Container(
width: 200,
height: 100,
color: Colors.blue,
child: const Center(child: Text('淡入动画')),
),
);
}
}
// 在页面中使用
class DemoPage extends StatefulWidget {
const DemoPage({super.key});
State<DemoPage> createState() => _DemoPageState();
}
class _DemoPageState extends State<DemoPage> with SingleTickerProviderStateMixin {
late AnimationController _controller;
late Animation<double> _animation;
void initState() {
super.initState();
_controller = AnimationController(
duration: const Duration(seconds: 2),
vsync: this,
);
_animation = Tween<double>(begin: 0, end: 1).animate(_controller);
_controller.forward(); // 启动动画
}
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: FadeInWidget(animation: _animation), // 直接使用 AnimatedWidget
),
);
}
void dispose() {
_controller.dispose();
super.dispose();
}
}
缩放动画按钮
class ScaleButton extends AnimatedWidget {
const ScaleButton({
Key? key,
required Animation<double> animation,
this.onPressed,
}) : super(key: key, listenable: animation);
final VoidCallback? onPressed;
Widget build(BuildContext context) {
final animation = listenable as Animation<double>;
return Transform.scale(
scale: animation.value, // 缩放值(如 1.0 到 1.5)
child: ElevatedButton(
onPressed: onPressed,
child: const Text('点击放大'),
),
);
}
}
// 触发逻辑
class InteractiveDemo extends StatefulWidget {
const InteractiveDemo({super.key});
State<InteractiveDemo> createState() => _InteractiveDemoState();
}
class _InteractiveDemoState extends State<InteractiveDemo> with SingleTickerProviderStateMixin {
late AnimationController _controller;
late Animation<double> _animation;
void initState() {
super.initState();
_controller = AnimationController(
duration: const Duration(milliseconds: 300),
vsync: this,
);
_animation = Tween<double>(begin: 1, end: 1.5).animate(_controller);
}
void _triggerAnimation() {
_controller.forward().then((_) => _controller.reverse()); // 点击后放大再恢复
}
Widget build(BuildContext context) {
return Center(
child: ScaleButton(
animation: _animation,
onPressed: _triggerAnimation,
),
);
}
}
旋转动画
class SpinningLoader extends AnimatedWidget {
const SpinningLoader({
Key? key,
required Animation<double> animation,
}) : super(key: key, listenable: animation);
Widget build(BuildContext context) {
final animation = listenable as Animation<double>;
return Transform.rotate(
angle: animation.value * 2 * 3.14159, // 弧度值(0 到 2π)
child: const Icon(Icons.refresh, size: 50),
);
}
}
// 循环动画配置
class LoaderDemo extends StatefulWidget {
const LoaderDemo({super.key});
State<LoaderDemo> createState() => _LoaderDemoState();
}
class _LoaderDemoState extends State<LoaderDemo> with SingleTickerProviderStateMixin {
late AnimationController _controller;
void initState() {
super.initState();
_controller = AnimationController(
duration: const Duration(seconds: 1),
vsync: this,
)..repeat(); // 无限循环
}
Widget build(BuildContext context) {
return Center(
child: SpinningLoader(
animation: _controller, // 直接传入 Controller(其本身是 Animation<double>)
),
);
}
}
注意点
性能优化:
- 避免重建昂贵组件: 在
build方法中尽量减少复杂计算或嵌套过深的组件,防止动画卡顿。 - 使用
const子组件:若子组件静态,标记为const以减少重复构建。
常见问题:
- 动画未启动: 确保
AnimationController已调用forward()或repeat()。 - 内存泄漏: 必须在页面销毁时调用
_controller.dispose()。
最佳实践:
- 封装自定义
AnimatedWidget: 为每个动画类型创建独立类,提高代码可读性。 - 结合
Tween使用: 通过Tween定义动画值范围,使动画更可控。
构造函数
const AnimatedWidget({
Key? key,
required this.listenable,
}) : super(key: key);
属性
| 属性名 | 属性类型 | 说明 |
|---|---|---|
listenable | Listenable | 核心监听对象(如 Animation),值变化时自动调用 build 方法重建 UI。 |
key | Key? | 组件标识符,用于优化渲染和状态管理。 |
关键属性解析:
listenable: 这是AnimatedWidget的核心属性,必须传入一个实现了Listenable接口的对象(如AnimationController或Animation)。其作用机制是注册一个监听器,当动画值更新时,AnimatedWidget会自动调用build方法,无需手动管理状态更新。 注意: 若传入的Animation未启动或未添加监听,动画将不会生效。