Flutter入门:动画相关
Posted BennuCTech
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Flutter入门:动画相关相关的知识,希望对你有一定的参考价值。
动画
在flutter中,如果想让某个widget执行动画,需要用一个动画类的widget封装一下,比如一个图片
Center(
child: Image.asset(xxxxxx),
),
想实现透明度动画,使用FadeTransition,如下
Center(
child: FadeTransition(
opacity: _speakAnimation,
child: Image.asset(R.assetsLiveSpeak),
),
),
关键是opacity,是一个Animation,要想实现一个动画,还需要一个Tween和一个AnimationController。
Tween就是Animation。Tween还需要一个AnimationController,他们的创建及定义如下:
class _XXX extends State<XXXX> with SingleTickerProviderStateMixin
AnimationController _speakController;
Animation _speakAnimation;
@override
void initState()
super.initState();
_speakController = AnimationController(
vsync: this,
duration: Duration(seconds: 2),
);
_speakAnimation = Tween(
begin: 1.0,
end: 0.0,
).animate(_speakController);
_speakAnimation.addStatusListener((status) //监听动画
if(status == AnimationStatus.completed)
//todo
);
...
可以看到Tween定义的是动画的起始和结束状态(这里就是透明度的值)。而AnimationController主要是定义时长。
另外Tween可以添加动画监听(addStatusListener),一共有四种状态
enum AnimationStatus
/// The animation is stopped at the beginning.
dismissed,
/// The animation is running from beginning to end.
forward,
/// The animation is running backwards, from end to beginning.
reverse,
/// The animation is stopped at the end.
completed,
但是这样还差最后一步,启动动画,因为我们需求是页面一展示即播放,所以在build函数中forward一下即可(当然还可以在其他时机播放),代码如下:
class _XXX extends State<XXXX> with SingleTickerProviderStateMixin
AnimationController _speakController;
Animation _speakAnimation;
@override
void initState()
super.initState();
_speakController = AnimationController(
vsync: this,
duration: Duration(seconds: 2),
);
_speakAnimation = Tween(
begin: 1.0,
end: 0.0,
).animate(_speakController);
_speakAnimation.addStatusListener((status)
if(status == AnimationStatus.completed)
//todo
);
...
Widget build(BuildContext context)
_speakController.forward(); //播放动画
return Stack(
children: <Widget>[
Center(
child: FadeTransition(
opacity: _speakAnimation,
child: Image.asset(R.assetsLiveSpeak),
),
),
...
动画卡顿
从今天的一个需求说起吧,实现一个按钮呼吸效果,很简单,就是使用一个缩放动画即可,如下:
class _xxx extends State<xxx> with SingleTickerProviderStateMixin
AnimationController _animationController;
Animation _animation;
@override
void initState()
super.initState();
_animationController = AnimationController(
vsync: this,
duration: Duration(milliseconds: 800),
);
_animation = Tween(
begin: 0.8,
end: 1.0,
).animate(_animationController);
@override
void dispose()
_animationController.dispose();
super.dispose();
@override
Widget build(BuildContext context)
_animationController.repeat(reverse: true);
return Stack(
alignment: Alignment.center,
children: [
...
Column(
children: [
...
ScaleTransition(
scale: _animation,
child: TextButton(
onPressed: widget.onOpen,
child: Container(
width: 120,
height: 60,
padding: EdgeInsets.only(bottom: 8),
alignment: Alignment.center,
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage(R.assetsLiveRedPackageBtn)
)
),
child: Text(
"领取",
style: TextStyle(
fontSize: 22,
fontWeight: FontWeight.bold,
color: Color(0xFFB34D35)
),
),
),
),
),
...
],
)
],
);
动画效果是从0.8倍扩大到1.0,然后reverse,一直repeat即可。
但是运行后发现动画出现了异常,动画扩大到1.0后会快速小幅度缩放一次,然后才会还原到0.8
这明显不是我们想要的动画效果,后来我们尝试了其他动画,都有类似的效果。
但是在其他页面上的动画就不会出问题,所以最后排查发现是该页面的定时器影响到了动画。
这个页面里有一个倒计时,通过Timer来更新其中倒计时的文字,而更新使用了setState进行重绘,这样在动画执行到1秒的时候(扩大到1.0又缩回一点的时候)倒计时更新了,由于是setState,所以动画widget也重绘了(这样又变回1.0大小了),然后才缩回0.8
解决方法就是新增一个StatefulWidget类,将Timer和倒计时相关的组件放到这个类中实现,这样倒计时更新只会刷新这一部分,不会刷新动画组件,如下:
class TimerText extends StatefulWidget
int time;
TimerText(this.time);
@override
State<StatefulWidget> createState()
return _TimerText();
class _TimerText extends State<TimerText>
Timer timer;
@override
void initState()
super.initState();
timer = Timer.periodic(Duration(seconds: 1), (timer)
setState(()
if(widget.time <= 0)
timer.cancel();
else
widget.time--;
);
);
@override
void dispose()
timer.cancel();
super.dispose();
@override
Widget build(BuildContext context)
return Text(
"$widget.times",
style: TextStyle(
fontSize: 14,
color: Color(0xFFF9D873)
),
);
关注公众号:BennuCTech,获取更多干货!
以上是关于Flutter入门:动画相关的主要内容,如果未能解决你的问题,请参考以下文章
Flutter 实际开发常用工具类(全局提示,请求封装,常用窗帘动画及布局)