从零开始的 Flutter 动画
前言
动画本质是在一段时间内不断改变屏幕上显示的内容,从而产生视觉暂留现象。
动画一般可分为两类:
补间动画:补间动画是一种预先定义物体运动的起点和终点,物体的运动方式,运动时间,时间曲线,然后从起点过渡到终点的动画。
基于物理的动画:基于物理的动画是一种模拟现实世界运动的动画,通过建立运动模型来实现。例如一个篮球🏀从高处落下,需要根据其下落高度,重力加速度,地面反弹力等影响因素来建立运动模型。
Flutter 中的动画
Flutter 中有多种类型的动画,先从一个简单的例子开始,使用一个 AnimatedContainer
控件,然后设置动画时长 duration
,最后调用 setState
方法改变需要变化的属性值,一个动画就创建了。
代码如下
1 | import 'package:flutter/material.dart'; |
这是一个隐式动画,除此之外还有显式动画,Hreo 动画,交织动画。
基础概念
Flutter 动画是建立在以下的概念之上。
Animation
Flutter 中的动画系统基于 Animation
对象, 它是一个抽象类,保存了当前动画的值和状态(开始、暂停、前进、倒退),但不记录屏幕上显示的内容。UI 元素通过读取 Animation
对象的值和监听状态变化运行 build
函数,然后渲染到屏幕上形成动画效果。
一个 Animation
对象在一段时间内会持续生成介于两个值之间的值,比较常见的类型是 Animation<double>
,除 double
类型之外还有 Animation<Color>
或者 Animation<Size>
等。
1 | abstract class Animation<T> extends Listenable implements ValueListenable<T> { |
AnimationController
带有控制方法的 Animation
对象,用来控制动画的启动,暂停,结束,设定动画运行时间等。
1 | class AnimationController extends Animation<double> |
Tween
用来生成不同类型和范围的动画取值。
1 | class Tween<T extends dynamic> extends Animatable<T> { |
Curve
Flutter 动画的默认动画过程是匀速的,使用 CurvedAnimation
可以将时间曲线定义为非线性曲线。
1 | class CurvedAnimation extends Animation<double> with AnimationWithParentMixin<double> { |
Ticker
Ticker
用来添加每次屏幕刷新的回调函数 TickerCallback
,每次屏幕刷新都会调用。类似于 Web 里面的 requestAnimationFrame
方法。
1 | class Ticker { |
隐式动画
隐式动画使用 Flutter 框架内置的动画部件创建,通过设置动画的起始值和最终值来触发。当使用 setState
方法改变部件的动画属性值时,框架会自动计算出一个从旧值过渡到新值的动画。
比如 AnimatedOpacity
部件,改变它的 opacity
值就可以触发动画。
1 | import 'package:flutter/material.dart'; |
除了 AnimatedOpacity
外,还有其他的内置隐式动画部件如:AnimatedContainer
, AnimatedPadding
, AnimatedPositioned
, AnimatedSwitcher
, AnimatedAlign
等。
显式动画
显式动画指的是需要手动设置动画的时间,运动曲线,取值范围的动画。将值传递给动画部件如: RotationTransition
,最后使用一个AnimationController
控制动画的开始和结束。
1 | import 'dart:math'; |
除了 RotationTransition
外,还有其他的显示动画部件如:FadeTransition
, ScaleTransition
, SizeTransition
, SlideTransition
等。
Hero 动画
Hero 动画指的是在页面切换时一个元素从旧页面运动到新页面的动画。Hero 动画需要使用两个 Hero
控件实现:一个用来在旧页面中,另一个在新页面。两个 Hero
控件需要使用相同的 tag
属性,并且不能与其他tag
重复。
1 | // 页面 1 |
交织动画
交织动画是由一系列的小动画组成的动画。每个小动画可以是连续或间断的,也可以相互重叠。其关键点在于使用 Interval
部件给每个小动画设置一个时间间隔,以及为每个动画的设置一个取值范围 Tween
,最后使用一个 AnimationController
控制总体的动画状态。
Interval
继承至 Curve
类,通过设置属性 begin
和 end
来确定这个小动画的运行范围。
1 | class Interval extends Curve { |
这是一个由 5 个小动画组成的交织动画,宽度,高度,颜色,圆角,边框,每个动画都有自己的动画区间。
1 | import 'package:flutter/material.dart'; |
物理动画
物理动画是一种模拟现实世界物体运动的动画。需要建立物体的运动模型,以一个物体下落为例,这个运动受到物体的下落高度,重力加速度,地面的反作用力等因素的影响。
1 | import 'package:flutter/material.dart'; |
总结
本文介绍了 Flutter 中多种类型的动画,分别是
- 隐式动画
- 显式动画
- Hero 动画
- 交织动画
- 基于物理的动画
一个动画的主要因素有
Animation
动画对象AnimationController
动画控制器Tween
动画取值范围Curve
动画运动曲线
Flutter 动画基于类型化的 Animation
对象,Widgets
通过读取动画对象的当前值和监听状态变化重新运行 build
函数,不断变化 UI 形成动画效果。
参考
Flutter animation basics with implicit animations