Flutter学习之动画篇,理解有限,各位看客多多指点,多多包涵~
普通动画
在Flutter当中设置动画,需要使用动画控制器(AnimationController),使用它来控制动画的时间,开始,反向,暂停,等操作,
AnimationController _mAnimationController;
_mAnimationController = new AnimationController(
vsync: this,
duration: Duration(seconds: 5),
);
AnimationController 参数介绍:
- 参数一: vsync参数,存在vsync时会防止屏幕外动画(动画的UI不在当前屏幕时)消耗不必要的资源,通常情况使用with SingleTickerProviderStateMixin即可
class _AnimationPageState extends State with SingleTickerProviderStateMixin {
}
补充:
如果项目中只有一个动画使用的是 SingleTickerProviderStateMixin,项目中有2个以上的动画则使用TickerProviderStateMixin
- 参数二:duration参数:用来设置动画执行时间
- _mAnimationController.forward() //开始执行动画
- _mAnimationController.reverse() //反向执行动画
- _mAnimationController.reset() //重置
- _mAnimationController.dispose() //删除/停止动画
- _mAnimationController.repeat();//重复执行
Animation实例有2中状态:
- Animation<double>改变的是帧状态
- Animation<Color>改变的是颜色状态
接下来介绍的是 Animation<double>,设置动画,最后会为大家带来改变Animation<Color>的例子,大家可以尝试的写一下~,
Animation<double>:Tween补间动画:
Animation<double> _mAnimation;
_mAnimation = new Tween<double>(begin: 0, end: 200)
//添加动画控制器
.animate(_mAnimationController)
..addListener(() {
setState(() {
print('_mAnimationValue:${_mAnimationValue}');
_mAnimationValue = _mAnimation.value;
});
})
..addStatusListener((status) {
setState(() {
print('status:${status}');
_mAnimationStaus = status;
});
});
Tween参数:
- begin 开始
- end 结束
然后通过animate()将动画控制器(AnimationController)添加到Tween参数当中.这里结合起来可以理解为,5秒内从0,变化到200,_mAnimation.value就是每秒获取的状态
细心的同学可能会发现,这里的…addListener()是什么意思
..addListener(() {
setState(() {
print('_mAnimationValue:${_mAnimationValue}');
_mAnimationValue = _mAnimation.value;
});
})
..addStatusListener((status) {
setState(() {
print('status:${status}');
_mAnimationStaus = status;
});
其实啊,这是Dart中的语法,叫做联级符号,和这样写是一样的效果:
_mAnimation = new Tween<double>(begin: 0, end: 200)
//添加动画控制器
.animate(_mAnimationController);
_mAnimation.addListener(() {
setState(() {
print('_mAnimationValue:${_mAnimationValue}');
_mAnimationValue = _mAnimation.value;
});
});
_mAnimation.addStatusListener((status) {
setState(() {
print('status:${status}');
_mAnimationStaus = status;
});
});
- addListener() 他可以为Animation添加帧监听,每一帧都会被调用,通过setState()来触发
- addStatusListener() 他可以为Animation添加’动画状态改变’监听
addStatusListener 用來监听动画当前状态
* dismissed 动画在开始处停止。
* forward, 动画从头到尾都在运行。
* reverse 动画正在向后运行,从头到尾。
* completed 动画在结尾处停止。
还有一种方式:
//创建动画控制器
AnimationController _mAnimationController;
_mAnimationController = new AnimationController(
vsync: this,
duration: Duration(seconds: 5),
);
//执行动画
_mAnimationController.forward();
@override
Widget build(BuildContext context) {
return FadeTransition(
//设置渐变动画
opacity: _tweenAnimation,
child: ;
);
}
Curve:
Curve官方给的是’曲线’,但我感觉它类似于android的插值器(Interpolator)
Curve事例:Curve参考文档
_mAnimation通过chain()方法来添加Curve()
来看看完整代码吧:
建议在initState()初始化时来创建对象;
@override
void initState() {
//初始刷Controller设置执行时间
_mAnimationController = new AnimationController(
vsync: this,
duration: Duration(seconds: 5),
);
//设置变化区间 并监听
_mAnimation = new Tween<double>(begin: 0, end: 200)
//执行曲线 类似于android中的插值器Interpolator 默认Curves.linear
.chain(new CurveTween(curve: Curves.bounceIn))
//添加动画控制器
.animate(_mAnimationController);
_mAnimation.addListener(() {
setState(() {
print('_mAnimationValue:${_mAnimationValue}');
_mAnimationValue = _mAnimation.value;
});
});
_mAnimation.addStatusListener((status) {
setState(() {
print('status:${status}');
_mAnimationStaus = status;
});
});
/**
* addStatusListener 用來监听动画当前状态
* dismissed 动画在开始处停止。
* forward, 动画从头到尾都在运行。
* reverse 动画正在向后运行,从头到尾。
* completed 动画在结尾处停止。
*/
super.initState();
}
Container(
alignment: Alignment.center,
child: Column(
children: [
GestureDetector(
onTap: () {
//重置
_mAnimationController.reset();
//开始
_mAnimationController.forward();
},
child: Text("开始",style: TextStyle(fontSize: 25),),
),
Container(
width: _mAnimationValue,
height: _mAnimationValue,
child: FlutterLogo(),
)
],
),
)
最后需要在页面消失的时候将动画控制器也给销毁掉,这样能更好的资源回收.
@override
void dispose() {
// TODO: implement dispose
//资源回收
_mAnimationController.dispose();
super.dispose();
}
效果图(1.1):
AnimatedWidget
AnimatedWidget其实就是简化了addListener()方法,只需要继承自AnimatedWidget()就可以实现动画效果
AnimationController _mAnimationController;
Animation<double> _mAnimation;
@override
void initState() {
//初始刷Controller设置执行时间
_mAnimationController = new AnimationController(
vsync: this,
duration: Duration(seconds: 5),
);
//设置变化区间 并监听
_mAnimation = new Tween<double>(begin: 0, end: 200)
//执行曲线 类似于android中的插值器Interpolator 默认Curves.linear
.chain(new CurveTween(curve: Curves.bounceIn))
//添加动画控制器
.animate(_mAnimationController);
//不用在写addListener()监听方法监听帧变化了!
super.initState();
}
继承自AnimatedWidget,将Animation<double>参数传进来,然后给到父类的listenable,在获取到value设置给布局即可.
class AnimationWidget extends AnimatedWidget {
AnimationWidget({Key key, Animation<double> animaiton})
: super(key: key, listenable: animaiton);
@override
Widget build(BuildContext context) {
//通过父类方法listenable来获取Animation<double>对象
Animation<double> _mAnimation = listenable;
return Container(
width: _mAnimation.value,
height: _mAnimation.value,
child: FlutterLogo(),
);
}
}
资源回收:
@override
void dispose() {
// TODO: implement dispose
//资源回收
_mAnimationController.dispose();
super.dispose();
}
Container(
alignment: Alignment.center,
child: Column(
children: [
GestureDetector(
onTap: () {
//重置
_mAnimationController.reset();
//开始
_mAnimationController.forward();
},
child: Text("开始",style: TextStyle(fontSize: 25),),
),
//调用AnimationWidget将Animaiton传给他即可~!
AnimationWidget(animaiton: _mAnimation),
],
),
),
效果图(1.2):
AnimatedBuilder
AnimatedBuilder也是简化了addListener()方法,直接将布局和动画给到AnimatedBuilder,就可以实现动画效果
动画条件不变:
AnimationController _mAnimationController;
Animation<double> _mAnimation;
@override
void initState() {
//初始刷Controller设置执行时间
_mAnimationController = new AnimationController(
vsync: this,
duration: Duration(seconds: 5),
);
//设置变化区间 并监听
_mAnimation = new Tween<double>(begin: 0, end: 200)
//执行曲线 类似于android中的插值器Interpolator 默认Curves.linear
.chain(new CurveTween(curve: Curves.bounceIn))
//添加动画控制器
.animate(_mAnimationController);
//不用在写addListener()监听方法监听帧变化了!
super.initState();
}
创建AnimatedBuilder必填参数是:
builder: (BuildContext context, Widget child) {} ); 返回的是动画
animation也是必填参数
AnimatedBuilder(
child: Container(
color: Colors.yellow,
width: 100,
height: 100,
child: FlutterLogo(),
),
builder: (BuildContext context, Widget child) {
return Container(
//这次不从0开始显示,从100开始显示看看效果~
width: _mAnimation.value + 100,
height: _mAnimation.value + 100,
//这里的child就是上边给的FlutterLogo()
child: child,
);
},
//必填参数将动画给导布局图片
animation: _mAnimation,
)
效果图(1.3):
Animation<Color>事例:
我是采用的AnimatedWidget办法
第一步还是不会变的,还是设置动画控制器(AnimationController),然后设置Color颜色变化状态,由Colors.amber颜色变化到 Colors.tealAccent颜色
@override
void initState() {
//初始刷Controller设置执行时间
_mAnimationController = new AnimationController(
vsync: this,
duration: Duration(seconds: 5),
);
//改变颜色状态
_mAnimationColor =
new ColorTween(begin: Colors.amber, end: Colors.tealAccent)
.animate(_mAnimationController);
super.initState();
}
我这里的Animation<double>和Animation<Color>复用的,建议大家分开写!
class AnimationWidget extends AnimatedWidget {
//isColor true是Animation<Color>类型
// false 是Animation<double>类型
bool isColor;
AnimationWidget(
{Key key,
Animation<Color> animaitonColor,
Animation<double> animaitonDouble,
@required this.isColor})
: super(key: key, listenable:isColor == true? animaitonColor :animaitonDouble);
Animation<Color> _mAnimationColor;
Animation<double> _mAnimationDouble;
@override
Widget build(BuildContext context) {
//通过父类方法listenable来获取Animation<double>对象
if (isColor) {
_mAnimationColor = listenable;
} else {
_mAnimationDouble = listenable;
}
return isColor == true
? Container(
width: 100,
height: 100,
color: _mAnimationColor.value,
child: FlutterLogo(),
)
: Container(
width: _mAnimationDouble.value,
height: _mAnimationDouble.value,
child: FlutterLogo(),
);
}
}
资源回收
@override
void dispose() {
// TODO: implement dispose
//资源回收
_mAnimationController.dispose();
super.dispose();
}
效果图(1.4):
上一章:Flutter Ink,InkWell,InkResponse水波纹实现(2.3)
原创不易,您的点赞就是对我最大的支持,请留下您的点赞吧~