第 22 章摘要。 动画

注意

本书于 2016 年春季出版,之后再未更新。 书中有许多内容仍然有价值,但有些内容已过时,有些主题不再完全正确或完整。

你已经知道可以使用 Xamarin.Forms 计时器或 Task.Delay 创建自己的动画,但使用 Xamarin.Forms 提供的动画工具通常更容易。 有三个类可以实现这些动画:

通常,动画以可绑定属性支持的属性为目标。 这不是必需的,但这些是对更改做出动态反应的唯一属性。

这些动画没有 XAML 接口,但可以使用第 23 章触发器和行为中进行介绍。

探索基本动画

基本动画功能是 ViewExtensions 类中的扩展方法。 这些方法适用于派生自 VisualElement 的任何对象。 此类最简单的动画以 Chapter 21. Transforms 中讨论的转换属性为目标。

AnimationTryout 演示了 ButtonClicked 事件处理程序如何调用 RotateTo 扩展方法以将按钮旋转一周

RotateTo 方法在四分之一秒的时间内(默认情况下)将 ButtonRotation 属性从 0 更改为 360。 但是,如果再次点击 Button,则不会执行任何操作,因为 Rotation 属性已经是 360 度。

设置动画持续时间

RotateTo 的第二个自变量是持续时间(毫秒)。 如果设置为较大的值,则在动画演示过程中点击 Button 将以当前角度开始一个新的动画。

相对动画

RelRotateTo 方法通过将指定的值添加到现有值来执行相对旋转。 此方法允许多次点击 Button,每次 Rotation 属性增加 360 度。

等待动画

ViewExtensions 中的所有动画方法都返回 Task<bool> 对象。 这意味着可以使用 ContinueWithawait 来定义一系列连续动画。 如果动画在没有中断的情况下完成,则 bool 完成返回值为 false如果通过 CancelAnimation 方法(该方法将取消在同一元素上设置的 ViewExtensions 中的其他方法启动的所有动画)取消了该动画,返回值则为 true

合成动画

可以混合等待和非等待的动画来创建复合动画。 这些是 ViewExtensions 中面向 TranslationXTranslationYScale 转换属性的动画:

请注意,TranslateTo 可能会影响 TranslationXTranslationY 的属性。

Task.WhenAll 和 Task.WhenAny

还可以使用 Task.WhenAll(在多个任务都结束时发出信号)和 Task.WhenAny(在多个任务中的第一个任务结束后发出信号)来管理同步动画。

旋转和定位点

调用 ScaleToRelScaleToRotateToRelRotateTo 方法时,可以将 AnchorXAnchorY 属性设置为指示缩放和旋转的中心。

CircleButton 通过围绕页面中心旋转 Button 来演示此技术

缓动函数

通常,动画从开始值到结束值都是线性的。 缓动函数会导致动画在整个演示过程中加速或减速。 动画方法的最后一个可选自变量为 Easing 类型,该类定义了 11 个 Easing 类型的静态只读字段:

In 后缀表示该效果位于动画的开头,Out 表示该效果位于结尾,InOut 表示该效果位于动画的开头和结尾。

BounceButton 示例演示了如何使用缓动函数

自己的缓动函数

还可以通过将 Func<double, double> 传递到 Easing 构造函数来定义自己的缓动函数。 Easing 还定义了从 Func<double, double>Easing 的隐式转换。 缓动函数的自变量始终处于 0 到 1 的范围内,因为动画会从头到尾以线性方式演示。 函数通常返回介于 0 到 1 之间的值,但可能短暂地为负值或大于 1(与 SpringInSpringOut 函数的情况相似),或者,如果你很清楚当前执行的操作,则可能不会遵循该规则

UneasyScale 示例演示了一个自定义缓动函数,CustomCubicEase 演示了另一个函数

SwingButton 示例也演示了一个自定义缓动函数,还演示了在一系列旋转动画中更改 AnchorXAnchorY 属性的方法

Xamarin.FormsBook.Toolkit 库具有 JiggleButton 类,该类使用自定义缓动函数使按钮在单击时抖动. JiggleButtonDemo 示例对此进行了演示

进入动画

一种常见的动画类型,在页面第一次显示时出现。 此类动画可以在页面的 OnAppearing 重写中启动。 对于这些动画,最佳做法是针对动画后所需的页面显示方式设置 XAML,然后通过代码初始化布局并对其进行动画处理

FadingEntrance 示例使用 FadeTo 扩展方法淡入页面内容

SlidingEntrance 示例使用 TranslateTo 扩展方法从侧面滑入页面内容

SwingingEntrance 示例使用 RotateYTo 扩展方法对 RotationY 属性进行动画处理。 还可使用 RotateXTo 方法。

永久动画

“永久”动画是另一种极端情况,会一直运行到程序终止为止。 此类动画通常供演示之用。

FadingTextAnimation 示例使用 FadeTo 动画淡入和淡出两段文本

PalindromeAnimation 显示回文,然后按顺序将各个字母旋转 180 度,使它们全部上下颠倒。 然后,整个字符串将翻转 180 度,以读取与原始字符串相同的字符串。

CopterAnimation 示例将旋转出一个简单的 BoxView 直升机形状,同时围绕屏幕中心旋转

RotatingSpokes 使 BoxView 轮辐围绕屏幕中心旋转,然后旋转每个轮辐本身以创建有趣的图案

旋转轮辐的三重屏幕截图

但是,如 RotationBreakdown 示例中所示,从长远来看,逐渐增加元素的 Rotation 属性可能不起作用

SpinningImage 示例使用 RotateToRotateXToRotateYTo 使其看起来像是在 3D 空间中旋转位图

对 bounds 属性进行动画处理

ViewExtensions 中尚未演示的唯一扩展方法是 LayoutTo,该方法通过调用 Layout 方法有效地对只读 Bounds 属性进行动画处理。 此方法通常由 Layout 派生项调用,将在第 26 章 CustomLayouts 中进行讨论。

LayoutTo 方法应仅限于特殊用途。 BouncingBox 程序在 BoxView 从页面侧面反弹时使用该方法对其进行压缩和展开

XamagonXuzzle 示例使用 LayoutTo 在经典的 15-16 拼图的实现中移动磁贴,该拼图显示杂乱的图像而不是编号磁贴

Xamarin Xuzzle 的三重屏幕截图

自己的可等待动画

TryAwaitableAnimation 示例创建可等待动画。 在动画完成时,可以从方法返回 Task 对象并发出信号的关键类是 TaskCompletionSource

深入了解动画

Xamarin.Forms 动画系统可能会有些混乱。 除了 Easing 类,该动画系统还包括 ViewExtensionsAnimationAnimationExtension 类。

ViewExtensions 类

你已经了解了 ViewExtensions。 它定义了九种方法,这些方法返回 Task<bool>CancelAnimations。 9 个方法中的 7 个方法以转换属性为目标。 另外两个是 FadeTo(以 Opacity 属性为目标)和 LayoutTo(调用Layout 方法)。

Animation 类

Animation 类具有构造函数,该构造函数具有五个用于定义回调和完成方法的自变量以及动画参数。

可以通过 AddInsertWithConcurrentWithConcurrent 的重载添加子动画。

然后,通过调用 Commit 方法启动动画对象。

AnimationExtensions 类

AnimationExtensions 类主要包含扩展方法。 有多种版本的 Animate 方法,泛型 Animate 方法非常通用,因为它实际上是所需的唯一动画函数。

使用 Animation 类

ConcurrentAnimations 示例演示了具有多个不同动画的 Animation

子动画

ConcurrentAnimations 示例还演示了子动画,这些子动画使用(非常类似的)AddInsert 方法

高级动画方法之外的内容

ConcurrentAnimations 示例还演示了如何执行超出 ViewExtensions 方法所针对的属性的动画。 在一个示例中,一系列周期变长;在另一个示例中,将对 BackgroundColor 属性进行动画处理。

自己的可等待方法的更多信息

ViewExtensionsTranslateTo 不适用于 Easing.SpringOut 函数。 当缓动输出大于 1 时,它将停止。

Xamarin.FormsBook.Toolkit 库包含 MoreViewExtensions 类,该类具有不存在此问题的 TranslateXToTranslateYTo 扩展方法,以及用于取消这些动画的 CancelTranslateXToCancelTranslateYTo 方法。

SpringSlidingEntrance 演示了 TranslateXTo 方法

MoreExtensions 类还包含将 X 和 Y 转换结合的 TranslateXYTo 扩展方法以及 CancelTranslateXYTo 方法。

实现贝塞尔动画

也可以开发一个动画,使动画沿贝塞尔曲线的路径移动。 Xamarin.FormsBook.Toolkit 库包含 BezierSpline 结构,该结构封装贝塞尔曲线和 BezierTangent 枚举来控制方向。

MoreViewExtensions 类包含 BezierPathTo 扩展方法和 CancelBezierPathTo 方法。

BezierLoop 示例演示如何沿着贝塞尔路径对元素进行动画处理

使用 AnimationExtensions

彩色动画是标准集合中缺少的一种动画类型。 问题在于,在两个 Color 值之间没有正确的插入方法。 可以插入单独的 RGB 值,但与插入 HSL 值的有效性相同。

因此,Xamarin.FormsBook.Toolkit 库中的 MoreViewExtensions 类包含两个 Color 动画方法:RgbColorAnimationHslColorAnimation。 (还有两种取消方法:CancelRgbColorAnimationCancelHslColorAnimation)。

这两种方法都使用 ColorAnimation(通过调用 AnimationExtensions 中广泛的泛型 Animate 方法来执行动画)。

ColorAnimations 示例演示如何使用这两种彩色动画类型

构造动画

用 XAML 表达动画并将动画与 MVVM 结合使用有时会很有用。 这将在下一章第 23 章触发器和行为中进行介绍。