动画效果会对提升用户体验有着显著效果,一个漂亮的动画效果会让人眼前一亮,反正就是用这舒服,如果没有动画效果的加持,整个App会显的非常生涩难用.对于Flutter的动画,作为小白的我也是最近才刚刚接触,所以这里就说一下Futter中如何使用动画.
这一篇主要是来说如何在Flutter中实现一个最简单的动画,这里假设你已经对Flutter有一些基本的了解或者有一定的开发经验了.
构建基础
这里我们就以控制 Container组件中 margin 为示例.
首先我们先创建一个StatefulWidget有状态组件,同时需要混合 SingleTickerProviderStateMixin,至于 SingleTickerProviderStateMixin 是什么,后面我们会讲到,具体代码如下所示.
class FlutterAnimationWidget extends StatefulWidget {
@override
_FlutterAnimationWidgetState createState() => _FlutterAnimationWidgetState();
}
class _FlutterAnimationWidgetState extends State with SingleTickerProviderStateMixin {
}
我们接着创建一个受控Container,放在一个纵向布局中,具体如下所示.关于触发按钮的布局这里就不给过叙述了,不是本文的重点.
Container(
width: 200,
height: 50,
color: Colors.orangeAccent,
margin: EdgeInsets.only(top: 0),
),
构建动画
我们声明动画控制器 _animationController 和margin的top状态属性 _marginTop ,改造Container让margin受控于 _marginTop 的值.具体代码如下所示.
double _marginTop;
AnimationController _animationController;
Container(
…
margin: EdgeInsets.only(top: _marginTop),
…
),
紧接着我们就需要实现 _animationController 了, 假设我们设定动画运行时间为 300 毫秒,top的移动范围为[0, 50],那么具体代码就如下所示.
_marginTop = 0;
_animationController = AnimationController(duration: Duration(milliseconds: 300), vsync: this)…addListener(() {
setState(() {
_marginTop = _animationController.value * 50.0;
});
});
这里就要对上述代码进行说明一下, 首先是 AnimationController 这个动画控制类,动画控制类中的只能在给定的时间内线性生成 0 → 1 的数值(默认区间),所以我们需要映射成我们想要的数值就需要使用到 value 这个属性映射成我们想要的值,这里就是简单映射成 0 → 50.
那么我们可不可以改动默认区间呢?当然是可以的,这就需要使用到 lowerBound 和 upperBound 了.那么上面的代码就可以如下示例,两者的效果是一样的.
_animationController = AnimationController(duration: Duration(milliseconds: 300), lowerBound: 0, upperBound: 50, vsync: this)…addListener(() {
setState(() {
_marginTop = _animationController.value;
});
});
那么 代码中 vsync 指向 this,又是什么意思呢?这个简单的来说就是使用Ticker(而不是Timer)来驱动动画会防止屏幕外动画(动画的UI不在当前屏幕时,如锁屏时)消耗不必要的资源.还记得文章一开始状态组件混合 SingleTickerProviderStateMixin 吗?就是这个作用.如果一个组件内存在多个动画控制器,则可以使用 TickerProviderStateMixin .
如下是摘抄 <<Flutter 实战>> 中的对Ticker一段说明.
Flutter应用在启动时都会绑定一个SchedulerBinding,通过SchedulerBinding可以给每一次屏幕刷新添加回调,而Ticker就是通过SchedulerBinding来添加屏幕刷新回调,这样一来,每次屏幕刷新都会调用TickerCallback。使用Ticker(而不是Timer)来驱动动画会防止屏幕外动画(动画的UI不在当前屏幕时,如锁屏时)消耗不必要的资源,因为Flutter中屏幕刷新时会通知到绑定的SchedulerBinding,而Ticker是受SchedulerBinding驱动的,由于锁屏后屏幕会停止刷新,所以Ticker就不会再触发。
对于 addListener()
方法,是给 AnimationController 添加监听回调,并且每一帧都会回调一次.这个我们在里面调用 setState()
方法就能实现对状态组件UI的重建了.
当然了,除了 addListener()
帧监听回调方法之外,还有 addStatusListener()
动画状态的监听,监听的值如下所示.
状态 | 说明 |
---|---|
AnimationStatus.dismissed | 动画从 controller.reverse() 反向执行 结束时会回调此方法 |
AnimationStatus.forward | 执行 controller.forward() 会回调此状态 |
AnimationStatus.reverse | 执行 controller.reverse() 会回调此状态 |
AnimationStatus.completed | 动画从 controller.forward() 正向执行 结束时会回调此方法 |
使用的话,示例如下所示.
_animationController.addStatusListener((status) {
if (status == AnimationStatus.completed) print(“动画完成”);
});
构建完成动画控制器,但是不要忘了最后需要进行释放操作.代码如下所示.
@override
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级安卓工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年最新Android移动开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频
如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Android)
每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频**
如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Android)
[外链图片转存中…(img-Phn4P8KM-1710924681055)]