Flutter动画 1 - 实现一个最简单的动画,大牛整理

动画效果会对提升用户体验有着显著效果,一个漂亮的动画效果会让人眼前一亮,反正就是用这舒服,如果没有动画效果的加持,整个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.

那么我们可不可以改动默认区间呢?当然是可以的,这就需要使用到 lowerBoundupperBound 了.那么上面的代码就可以如下示例,两者的效果是一样的.

_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移动开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频
如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Android)
img

每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频**
如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Android)
[外链图片转存中…(img-Phn4P8KM-1710924681055)]

  • 10
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值