前言
flutter实现简单的旋转动画,和大家一起学习探讨。
先上效果图:
概述
Flutter中对动画进行了抽象,主要涉及Animation、Curve、Controller、Tween这四个角色。
Animation对象是一个在一段时间内依次生成一个区间(Tween)之间值的类,
它的四种状态:
dismissed:动画初始状态
forward:动画从头到尾播放状态
reverse:动画从尾到头播放状态
completed:动画完成状态
Tween ,它主要是弥补 AnimationController 动画值只能为 double 类型的不足,
我的理解是animation是以动画的时间区间为X轴,根据设定好的Tween的开始结束值为Y轴,
框架自动计算如何从开始点过渡到结束点。
需要注意的是当创建一个AnimationController时,需要传递一个vsync参数,存在vsync时会防止屏幕外动画(动画的UI不在当前屏幕时)消耗不必要的资源。通过将SingleTickerProviderStateMixin添加到类定义中,可以将stateful对象作为vsync的值。如果要使用自定义的State对象作为vsync时,请包含TickerProviderStateMixin。
class _AnimationDemoState extends State<AnimationDemo> with SingleTickerProviderStateMixin
_animationController = AnimationController(duration: Duration(seconds: 300), vsync: this);
通过Animation抽象类的addStatusListener();它可以给Animation添加“动画状态改变”监听器;动画开始、结束、正向或反向时会调用状态改变的监听器。
_animation = Tween<double>(
begin: 1,
end: 300,
).animate(_animationController)..addStatusListener((status) {
if (status == AnimationStatus.completed) {
// 动画完成后反转
_animationController.reverse();
} else if (status == AnimationStatus.dismissed) {
// 反转回初始状态时继续播放,实现无限循环
_animationController.forward();
}
通过点击按钮控制AnimationController控制动画,启动forward()、停止stop()
child: GestureDetector(
onTap: (){
if(isStartTrain == false){
_animationController.forward();
}else{
_animationController.stop();
}
setState(() {
isStartTrain = !isStartTrain;
});
},
以下是demo代码
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/screenutil.dart';
class AnimationDemo extends StatefulWidget {
AnimationDemo({Key key}) : super(key: key);
@override
_AnimationDemoState createState() {
return _AnimationDemoState();
}
}
class _AnimationDemoState extends State<AnimationDemo> with SingleTickerProviderStateMixin{
bool isStartTrain = false;
AnimationController _animationController;
Animation _animation;
@override
void initState() {
_animationController =
AnimationController(duration: Duration(seconds: 300), vsync: this);
_animation = Tween<double>(
begin: 1,
end: 300,
).animate(_animationController)..addStatusListener((status) {
if (status == AnimationStatus.completed) {
// 动画完成后反转
_animationController.reverse();
} else if (status == AnimationStatus.dismissed) {
// 反转回初始状态时继续播放,实现无限循环
_animationController.forward();
}
});
super.initState();
}
@override
void dispose() {
super.dispose();
}
@override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
backgroundColor: Colors.white,
body: SafeArea(
child: GestureDetector(
onTap: (){
if(isStartTrain == false){
_animationController.forward();
}else{
_animationController.stop();
}
setState(() {
isStartTrain = !isStartTrain;
});
},
child: Stack(
children: [
Positioned(
child: Center(
child: RotationTransition(
//设置动画的旋转中心
alignment: Alignment.center,
//动画控制器
turns: _animation,
child: Container(
width: ScreenUtil().setWidth(180),
height: ScreenUtil().setWidth(180),
decoration: BoxDecoration(
image:DecorationImage(
image: AssetImage("assets/images/bg_timer.png"),
fit: BoxFit.cover,
),
// color: Color(0xFFFF542C),
// borderRadius: BorderRadius.circular(1000)
),
),
),
),
),
Positioned(
child: Center(
child: Text(
'${isStartTrain?"结束":"开始"}',
style: TextStyle(
color: Color(0xFF201E24),
fontSize: ScreenUtil().setSp(28)),
)),
)
],
),
),
),
);
}
}
欢迎大家和我一起学习分享flutter,项目会持续更新新的学习demo
此项目的github地址:项目地址
下面是我们的公众号:flutter编程笔记(code9871)
公众号 不定期分享自己的学习想法