为了账号安全,请及时绑定邮箱和手机立即绑定

【备战春招】第10天 Flutter中的动画

标签:
Android

课程名称Flutter从入门到进阶 实战携程网App 一网打尽核心技术
课程章节:Flutter入门:Flutter必备基础【修炼基本功】
课程讲师CrazyCodeBoy

课程内容

Flutter 动画介绍

Android中的动画,大致可以分为两种:视图动画(View Animation)和属性动画(Property Animation)。其中视图动画又可以分为两种:补间动画(Tween Animation)和逐帧动画(Frame Animation),那么这些动画有什么区别呢?

  • 补间动画(Tween Animation)是根据动画的初始状态和结束状态,自动补充中间状态;
  • 逐帧动画(Frame Animation)需要开发人员提供每一帧的内容;
  • 视图动画(View Animation)只作用于视图上,不会改变控件的属性;
  • 属性动画(Property Animation)会实实在在地改变控件的属性;

Flutter中的动画也主要分成两种:补间动画(Tween Animation)和基于物理的动画(Physics-based animation),补间动画与 Android 的补间动画类似,开发者给出动画的初始状态和结束状态,Flutter 框架会自动补充中间状态。

基于物理的动画(Physics-based animation),这类动画的运动模拟了真实世界中的相似行为,比如抛出球的落点,跟球距离地面的高度,抛球的速度,球的质量都有关系。连接在弹簧上的球与连接在绳子上的球落下是不同的。基于物理的动画有以下的特点:

  • 动画的效果是遵循物理定律;
  • 能够依据初始的速度和加速度计算每一帧动画展示需要的数值;
  • 在受力平衡时,动画处于匀速运动或静止状态。

Flutter 动画的核心类

跟动画有关的 Flutter 基础类:

  • Animation,是Flutter动画库中的一个核心类,主要用来生成指导动画的值;
  • CurvedAnimation,是Animation的一个子类,将动画过程抽象为一个非线性曲线;
  • AnimationController,也是Animation的一个子类,用来管理Animation;
  • Tween,为补间动画提供动画从开始点到结束点的相关数值,比如生成从红到蓝之间的色值,或者从0到255等等;

1.1 Animation

Animation 类是Flutter 动画中的核心抽象类,类中声明了 Animation 的四种状态:

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,
}

类中声明了动画的值和状态两个重要的属性,可以通过下面这些回调方法获取这两个属性值。

//动画过程中值变化的回调方法
@override
  void addListener(VoidCallback listener) {
    _listenable.addListener(listener);
  }
//动画状态的回调方法
  @override
  void addStatusListener(AnimationStatusListener listener) {
    // status will never change.
  }

在Flutter中,Animation对象本身和UI渲染没有任何关系。Animation是一个抽象类,一个比较常用的Animation类的实现类是Animation,Animation 还可以生成除double之外的其他类型值,如:Animation 或 Animation;

1.2 CurvedAnimation

CurvedAnimation 类的主要作用是作为动画的插值器,插值器的实现是在 Curve 类中,定义了时间与数值的接口。

@override
  double transform(double t) {
    if (t == 0.0 || t == 1.0) {
      return t;
    }
    return super.transform(t);
  }

Curves 类定义了 13 种插值器,除此之外,还可以使用 Cubic 类来自定义构造插值器。

1.3 Tween

Tween是一个无状态(stateless)对象,需要begin和end值。Tween的唯一职责就是定义从输入范围到输出范围的映射。默认范围为0.0到1.0。

在 Tween 中定了一系列的估值器,除此之外,还可以使用通过CurvedAnimation 实现的CurveTween。

  • ReverseTween
  • ColorTween
  • SizeTween
  • RectTween
  • IntTween
  • StepTween
  • ConstantTween

1.3 AnimationController

AnimationController是一个动画的控制类,它提供了如下的方法:

  • forward(),启动动画;
  • reverse(),倒放动画;
  • reset(),重置动画,将其设置到动画的开始位置;
  • stop(),停止动画;

AnimationController派生自Animation,因此可以在需要Animation对象的任何地方使用。当创建一个AnimationController时,需要传递一个vsync参数,存在vsync时会防止屏幕外动画消耗不必要的资源,可以将Stateful对象作为vsync的值。

默认情况下,AnimationController是线性的产生0.0到1.0之间的值,每刷新一帧就产出一个数值。AnimationController在不使用的时候需要dispose,否则会造成资源的泄漏。

AnimatedWidget 与 AnimatedBuilder

除了使用AnimationController 给组件添加动画,还可以用 AnimatedWidget与AnimatedBuilder简化和重构对动画的使用。

AnimatedWidget可以理解为Animation的助手,使用它可以简化对动画的使用。在不使用AnimatedWidget的情况下需要手动调用动画的addListener()并在回调中添加setState()才能看到动画效果,AnimatedWidget将为开发人员简化这一操作。

AnimatedBuilder 是用于构建动画的通用widget,AnimatedBuilder对于希望将动画作为更大构建函数的一部分包含在内的更复杂的widget时非常有用,可以这样理解:AnimatedBuilder是拆分动画的一个工具类,借助它可以将动画和widget进行分离。AnimatedBuilder是渲染树中的一个独立的类, 与AnimatedWidget类似,AnimatedBuilder自动监听来自Animation对象的通知,不需要手动调用addListener()。

Hero动画

Hero动画可以对应 Android 中的转场动画,Android 中在两个Activity或者Fragment之间做出流畅的转场动画,给用户良好的体验。通过Hero,可以实现在两个路由之间,做出流畅的转场动画。由于在Flutter里面,Dialog也是路由,因此也完全适用于Dialog的切换上。Hexo 的构造函数:

 const Hero({
    Key key,
    @required this.tag,
    this.createRectTween,
    this.flightShuttleBuilder,
    this.placeholderBuilder,
    this.transitionOnUserGestures = false,
    @required this.child,
  }) : assert(tag != null),
       assert(transitionOnUserGestures != null),
       assert(child != null),
       super(key: key);
  • tag,用于关联两个Hero动画的标识;
  • createRectTween,定义目标Hero的边界,在从起始位置到目的位置的“飞行”过程中该如何变化;
  • child,定义动画所呈现的widget;

实现 Hexo 动画的步骤:

  • 将源控件和目标控件分别用Hero包裹;
  • 同时为源控件和目标控件设置相同的tag;
  • 给源路由页面添加路由跳转逻辑。

课程总结

总结起来 Flutter 中实现动画的几种方式:

方式 1

通过自定义AnimationController、插值器CurvedAnimation、估值器TweenAnimation来实现,这种方式的弊端是代码耦合严重,需要调用 setState() 意味着整个 State 类中的 build 方法就会被重新执行。

方式 2

通过 AnimatedWidget,好处是从 setState() 调用中的动画代码中分离出 widget 代码,不需要维护一个 State 对象来保存动画,会自动调用 addListener() 和 setState()。

弊端是需要新建一个类来继承自 AnimatedWidget,如果动画 Widget 有子 Widget,那么意味着它的子 Widget 也会重新 build。

方式 3

通过AnimatedBuilder,实现动画与 widget 的剥离,同时AnimatedBuilder 自动监听来自 Animation 对象的通知。
图片描述

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
移动开发工程师
手记
粉丝
11
获赞与收藏
16

关注作者,订阅最新文章

阅读免费教程

  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消