基础动画
- Animation:Flutter动画中的核心类,此类是抽象类,通常情况下使用其子类:AnimationController,可以获取当前动画的状态和值,也可以添加其状态变化监听和值变化监听。
- Curve:决定动画执行的曲线,和Android中的Interpolator(差值器)是一样的,负责控制动画变化的速率,系统已经封装了10多种动画曲线,详见Curves类。差值器
- AnimationController:动画控制器,控制动画的开始、停止。继承自Animation。
- Tween:映射生成不同范围的值,AnimationController的动画值是double类型的,如果需要颜色的变化,Tween可以完成此工作。
class AnimationWidgetState extends State<AnimationTestPage>
with SingleTickerProviderStateMixin {
late Animation<double> _animation;
late AnimationController _controller;
@override
void initState() {
super.initState();
_controller =
AnimationController(vsync: this, duration: const Duration(seconds: 1));
_animation = CurvedAnimation(parent: _controller, curve: Curves.bounceIn);
_animation = Tween<double>(begin: 0.0, end: 400).animate(_controller)
..addListener(() {
setState(() {});
});
_controller.forward();
}
@override
Widget build(BuildContext context) => MaterialApp(
home: Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Image.network(
'https://th.bing.com/th/id/OIP.3hG2qwUAodmXmKQuKe6pqAHaFj?w=240&h=180&c=7&r=0&o=5&dpr=2&pid=1.7',
height: _animation.value,
width: _animation.value,
),
TextButton(
onPressed: () {
_animation = Tween<double>(begin: 0.0, end: 400)
.animate(_controller)
..addListener(() {
setState(() {});
});
_controller.forward();
_controller.reverse();
},
child: const Text('开始播放')),
TextButton(
onPressed: () {
_animation = Tween<double>(begin: 400, end: 0.0)
.animate(_controller)
..addListener(() {
setState(() {});
});
_controller.forward();
_controller.reverse();
},
child: const Text('重置播放')),
],
),
),
),
);
}
还可以通过继承AnimatedWidget
方式实现
class AnimationWidget extends AnimatedWidget {
const AnimationWidget({Key? key, required Listenable listenable})
: super(key: key, listenable: listenable);
@override
Widget build(BuildContext context) {
var anim = listenable as Animation<double>;
return Image.network(
'https://th.bing.com/th/id/OIP.3hG2qwUAodmXmKQuKe6pqAHaFj?w=240&h=180&c=7&r=0&o=5&dpr=2&pid=1.7',
height: anim.value,
width: anim.value,
);
}
}
class AnimatedState extends State<AnimationTestPage>
with SingleTickerProviderStateMixin {
late Animation<double> _animation;
late AnimationController _controller;
@override
void initState() {
super.initState();
_controller =
AnimationController(vsync: this, duration: const Duration(seconds: 1));
_animation = CurvedAnimation(parent: _controller, curve: Curves.easeIn);
_animation = Tween<double>(begin: 0.0, end: 400).animate(_controller);
_animation.addStatusListener((status) {
print('动画状态 name=${status.name}, index=${status.index}');
});
_controller.forward();
}
@override
void dispose() {
_controller.dispose(); //页面销毁是回收动画资源
super.dispose();
}
@override
Widget build(BuildContext context) => MaterialApp(
home: Scaffold(
body: Center(
child: Column(
children: [
Column(
children: [
AnimationWidget(listenable: _animation),
TextButton(
onPressed: () {
_controller.reverse();
},
child: const Text('播放反转')),
TextButton(
onPressed: () {
_controller.forward();
},
child: const Text('播放正序')),
],
)
],
),
),
),
);
}
路由切换动画
路由添加跳转动画PageRouteBuilder
class AnimationPage1 extends StatelessWidget {
const AnimationPage1({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) => MaterialApp(
home: Scaffold(
body: Center(
child: Stack(
alignment: Alignment.center,
children: [
Image.network(
'https://th.bing.com/th/id/OIP.3hG2qwUAodmXmKQuKe6pqAHaFj?w=240&h=180&c=7&r=0&o=5&dpr=2&pid=1.7'),
ElevatedButton(
child: const Text('跳转'),
onPressed: () {
//路由地址跳转
// Navigator.of(context).popAndPushNamed('page2');
//IOS风格跳转
// Navigator.of(context).push(CupertinoPageRoute(
// builder: (context) => const AnimationPage2()));
Navigator.of(context).push(PageRouteBuilder(
transitionDuration: const Duration(milliseconds: 500),
pageBuilder: (BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation) {
return FadeTransition(
opacity: animation,
child: const AnimationPage2(),
);
}));
},
)
],
),
),
),
);
}
跳转的目标页面
class AnimationPage2 extends StatelessWidget {
const AnimationPage2({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) => MaterialApp(
home: Scaffold(
body: Center(
child: Stack(
alignment: Alignment.center,
children: [
Image.network(
'https://tse1-mm.cn.bing.net/th/id/R-C.40f1f5201a2c0d806a694dceeb057760?rik=79D7YC4k%2fkHsiQ&pid=ImgRaw&r=0'),
ElevatedButton(
child: const Text('关闭'),
onPressed: () {
Navigator.pop(context);
},
)
],
),
),
),
);
}
main() {
runApp(MaterialApp(
// home: const AnimationPage1(),
initialRoute: 'page1',
routes: {
'page1': (context) => const AnimationPage1(),
'page2': (context) => const AnimationPage2(),
},
));
}