Skip to content

Latest commit

 

History

History
130 lines (68 loc) · 6.86 KB

10. Flutter用户交互 - 动画.md

File metadata and controls

130 lines (68 loc) · 6.86 KB

Animations

Introduction

许多widget, 特别是Material widgets, 自带一些标准的动效. 也可以自定义这些效果.

动画类型 Animation types

动画类型: Tween和Physics-based

补间动画 Tween animation

补间动画, 定义好了起始点和结束点, 且通过时间线和曲线定义转场的时间和速度. 由框架计算起始点到结束点的转移.

物理动画 Physics-based animation

模拟真实世界的行为. 如, 抛出一个球, 什么时候在哪里掉落由抛出的速度和角度决定. 同样的, 把球扔到水里和扔到绳子上的弹性不一样.

通用动画模板 Common animation patterns

Animated list or grid
Shared element transition
Staggered animation

Overview

Flutter的动画基于Animation对象. Widget可以将这些动画对象放到build函数中, 读取动画当前的值, 监听状态的改变. 或者以这些动画对象为基础做出更复杂的动画.

Animation

动画基本的构成元素是Animation类. 一个animation描绘了特定类型的值在动画生命周期的变化. 大部分widget通过接收一个Animation对象的参数来实现动画, 它们读取Animation对象当前的动画的值到监听值的变化.

addListener

任何时候动画的值改变, animation通知所有监听者(addListener). 通常, 一个监听动画的State对象, 会在它的监听回调中调用自身的setState方法, 来通知widget需根据动画的新值重建.

这种模式比较通用, 因此有两种widget用来帮忙动画值改变时widget的重建: AnimatedWidget 和 AnimatedBuilder. 第一个, AnimatedWidget, 主要用于stateless animated widgets. 使用AnimatedWidget, 只需要继承它, 实现build函数. 第二个, AnimatedBuilder, 主要用于更加复杂的widget, 希望在大一点的build函数中包含一个动画. 使用AnimatedBuilder, 只要构建一个widget, 传入一个builder函数.

addStatusListener

AnimationStatus, 展示动画不同时间的进展. 任何时候动画的状态改变, animation会通知监听者(addStatusListener). 通常, animations以dismissed开始, 表示在动画的起点. 如, 动画进度从 0.0 到 1.0, 当它的值为0.0时, 为dismissed状态. 之后会进入到forward状态(从0.0到1.0), 也可能是reverse(从1.0到0.0). 最终动画到达终点(如, 1.0), 动画进入到completed 状态.

Animation­Controller

创建一个动画, 首先需要创建一个AnimationController. 和animation一样, AnimationController让你可以控制动画. 如, 可以告知controller播放动画, forwardstop 动画. 也可以fling(抛)动画, 使用物理仿真(如弹力)来播放动画.

当你创建一个动画控制器, 可以以它为基础开始构建其他动画. 如, 可以创建一个ReverseAnimation与原始动画一致, 方向相反的动画. 同样的, 也可以创建一个CurvedAnimation, 动画值由curve决定.

Tweens

为了0.0到1.0间隔中做动画, 在开始和结束值中插入一个Tween<T>. 特定类型的Tween的子类提供了指定类型的插值. 如, ColorTween主要用于颜色之间, RectTween主要用于rects中. 可以通过创建Tween的子类, 重写lerp函数, 来自定义插值.

tween只是定义如何在两个值之间插入值. 为了能够获取当前动画框架的混合值, 还需要一个animation来决定当前状态. 有两种方式来组合tween和一个animation来获取混合值.

    1. 可以计算tween在一个动画中的当前值. 这种方式对于那些已经监听动画的widget最有用, 因为widget在动画值改变时都需要重建.
    1. 可以基于一个动画来对tween做动画. animate函数返回一个合并了tween的新的Animation, 而不是返回一个简单的值. 当希望把一个新创建的动画, 应用到其他widget, 这种方法最有用. 可以读取当前合并了tween之后的值, 也可以监听所有值的改变.

Architecture

Scheduler

SchedulerBinding是一个单例类, 提现了Flutter时序安排的基元.

关键的基元是frame回调. 每次frame需要显示在屏幕上, flutter的引擎触发"begin frame"回调, scheduler多路传输给所有通过scheduleFrameCallback()注册的监听者. 所有这些回调会给定一个frame的时间戳, 来自任一历元的Duration格式. 因为所有回调有同样的时间, 这些回调触发的任何动画会完全同步的出现, 即使他们需要花费些许毫秒来执行.

Tickers

Ticker类接入scheduler的scheduleFrameCallback()机制, 在每次tick时唤起一个回调.

Ticker可以被开始和结束. 当开始的时候, 会返回一个Future, 这个Future在停止的时候

每次tick, Ticker提供回调, 时长为第一个tick开始至今的持续时间.

因为tickers在开始后, 总是相对第一个tick提供一个经过的时间, tickers都是同步的. 如果三个tick, 在两个frame的不同的时间下开启, 尽管如此他们也都会同步到同一个开启时间, 随后跟着lockstep触发每次tick.

Simulations

Simulation抽象类映射一个相对时间值(时间间隔)为double值, 有一个完成的概念.

原则上simulation是stateless的, 实现上有些simulations在需要的时不可避免的要改变状态(如, BouncingScrollSimulation and ClampingScrollSimulation)

Animatables

Animatable抽象类匹配特定类型的值为double.

Animatable类是无状态的不可变的.

Tweens

Tween抽象类, 匹配0.0-0.1中的double值给某一种类型的值(如, Color, 或者其他 double). 它是Animatable.

有一个概念上的输出类型(T), 开始值和结束值的类型, 和lerp

Tween类是无状态的不可变的.

Composing animatables

传递一个Animatable(父)到一个Animatable的chain()方法, 创建一个新的Animatable子类, ...

Curves

Curves抽象类匹配double范围从0.0-1.0 ...

Curve类是无状态不可变的

Animations

Animation抽象类提供给定类型的值, 动画的方向, 状态, 监听者声明注册回调, 每次状态/值改变时调用的该回调.

一些Animation的子类有一些永远不会改变的值(kAlwaysCompleteAnimation, kAlwaysDismissedAnimation, AlwaysStoppedAnimation); 在这些值上面注册回调没有效果, 回调永远不会调用.

Animation变体比较特别, 因为它可以用来表示0-1.0之间的double值, 这些值是Curve, Tween和一些Animation的子类所希望获取到的.

一些Animation的子类是无状态的, 只是用于转发监听者给父部件. 另外, 有些是有状态的.

Composable animations

大部分Animation的子类有一个确切的"父类"Animation. 他们由父类驱动.

CurvedAnimation子类继承自Animation类(父类)和一对Curve类.(前进或者倒退曲线), 且使用父类的值作为输入

Animation Controllers
Attaching animatables to animations

Tutorial

Hero animations

Staggered animations

...