中的简单动画 Xamarin.Forms

下载示例 下载示例

ViewExtensions 类提供可用于构造简单动画的扩展方法。 本文演示如何使用 ViewExtensions 类创建和取消动画。

ViewExtensions 提供以下可用于创建简单动画的扩展方法:

默认情况下,每个动画需要 250 毫秒。 但是,可以在创建动画时指定每个动画的持续时间。

注意

ViewExtensions 提供 LayoutTo 扩展方法。 但是,此方法旨在供布局用来对包含大小和位置更改的布局状态之间的过渡进行动画处理。 因此,它只应由子类使用 Layout

类中的 ViewExtensions 动画扩展方法都是异步的,并返回 对象 Task<bool> 。 如果动画完成,则返回值为 ;如果动画取消,true则返回值为 false 。 因此,动画方法通常应与 运算符一起使用 await ,以便可以轻松确定动画何时完成。 此外,还可以创建顺序动画,并在上一个方法完成后执行后续动画方法。 有关详细信息,请参阅 复合动画

如果要求让动画在后台完成,则可以 await 省略 运算符。 在此方案中,动画扩展方法将在启动动画后快速返回,动画在后台发生。 创建复合动画时,可以利用此操作。 有关详细信息,请参阅 复合动画

有关 运算符的详细信息 await ,请参阅 异步支持概述

单个动画

中的每个 ViewExtensions 扩展方法实现单个动画操作,该操作在一段时间内逐渐将属性从一个值更改为另一个值。 本部分探讨每个动画操作。

旋转

下面的代码示例演示如何使用 RotateTo 方法对 的 属性进行Image动画处理Rotation

await image.RotateTo (360, 2000);
image.Rotation = 0;

此代码通过在 2 秒 (2000 毫秒) 旋转高达 360 度,对实例进行动画 Image 处理。 方法 RotateTo 获取动画开头的当前 Rotation 属性值,然后从该值旋转到其第一个参数 (360) 。 动画完成后,图像的 Rotation 属性将重置为 0。 这可确保属性 Rotation 在动画结束后不会保持为 360,从而防止其他旋转。

以下屏幕截图显示了每个平台上正在进行的轮换:

旋转动画

注意

除了 RotateTo 方法,还有 RotateXToRotateYTo 方法分别对 和 RotationY 属性进行RotationX动画处理。

相对旋转

下面的代码示例演示如何使用 RelRotateTo 方法以增量方式增加或减少 RotationImage属性:

await image.RelRotateTo (360, 2000);

此代码通过在 2 秒 (2000 毫秒) 从起始位置旋转 360 度来对实例进行动画 Image 处理。 方法 RelRotateTo 获取动画开头的当前 Rotation 属性值,然后从该值旋转到值及其第一个参数 (360) 。 这可确保每个动画始终从起始位置旋转 360 度。 因此,如果在动画已在进行时调用新动画,它将从当前位置开始,并可能在不是 360 度增量的位置结束。

以下屏幕截图显示了每个平台上正在进行的相对旋转:

相对旋转动画

扩展

下面的代码示例演示如何使用 ScaleTo 方法对 的 属性进行Image动画处理Scale

await image.ScaleTo (2, 2000);

此代码通过在 2 秒 (2000 毫秒) 缩放到其大小的两倍来对实例进行动画 Image 处理。 方法 ScaleTo 获取当前 Scale 属性值 (动画开头的默认值 1) ,然后从该值缩放到其第一个参数 (2) 。 这会导致将图像的大小扩大为其大小的两倍。

以下屏幕截图显示了每个平台上正在进行的缩放:

缩放动画

注意

除了 ScaleTo 方法,还有 ScaleXToScaleYTo 方法分别对 和 ScaleY 属性进行ScaleX动画处理。

相对缩放

下面的代码示例演示如何使用 RelScaleTo 方法对 的 属性进行Image动画处理Scale

await image.RelScaleTo (2, 2000);

此代码通过在 2 秒 (2000 毫秒) 缩放到其大小的两倍来对实例进行动画 Image 处理。 方法 RelScaleTo 获取动画开头的当前 Scale 属性值,然后从该值缩放到值及其第一个参数 (2) 。 这可确保每个动画始终从起始位置缩放为 2。

使用定位点进行缩放和旋转

AnchorXAnchorY 属性设置 和 Scale 属性的缩放或旋转Rotation中心。 因此,它们的值也会影响 RotateToScaleTo 方法。

Image给定已放置在布局中心的 ,以下代码示例演示如何通过设置其 AnchorY 属性围绕布局中心旋转图像:

double radius = Math.Min(absoluteLayout.Width, absoluteLayout.Height) / 2;
image.AnchorY = radius / image.Height;
await image.RotateTo(360, 2000);

若要围绕布局的中心旋转 Image 实例, AnchorX 必须将 和 AnchorY 属性设置为相对于 宽度和高度的值 Image。 在此示例中, 的中心 Image 定义为位于布局的中心,因此默认值 AnchorX 0.5 不需要更改。 但是, AnchorY 属性被重新定义为从 顶部 Image 到布局中心点的值。 这可确保 Image 围绕布局的中心点进行 360 度的完全旋转,如以下屏幕截图所示:

具有定位点的旋转动画

翻译

下面的代码示例演示如何使用 TranslateTo 方法对 的 和 TranslationY 属性进行Image动画处理TranslationX

await image.TranslateTo (-100, -100, 1000);

此代码通过在 1 秒 (1000 毫秒) 进行水平和垂直转换来对实例进行动画 Image 处理。 方法 TranslateTo 同时将图像向左平移 100 像素,向上平移 100 像素。 这是因为第一个和第二个参数都是负数。 提供正数会将图像向右和向下转换。

以下屏幕截图显示了每个平台上正在进行的翻译:

翻译动画

注意

如果元素最初在屏幕外布局,然后转换为屏幕,则在转换后,元素的输入布局将保留在屏幕外,用户无法与之交互。 因此,建议将视图布局在其最终位置,然后执行任何所需的翻译。

淡入淡出

下面的代码示例演示如何使用 FadeTo 方法对 的 属性进行Image动画处理Opacity

image.Opacity = 0;
await image.FadeTo (1, 4000);

此代码通过在 4 秒 (4000 毫秒) 内淡出实例,对实例进行动画 Image 处理。 方法 FadeTo 获取动画开头的当前 Opacity 属性值,然后从该值淡入到其第一个参数 (1) 。

以下屏幕截图显示了每个平台上的淡入状态:

淡化动画

复合动画

复合动画是动画的顺序组合,可以使用 运算符创建 await ,如以下代码示例所示:

await image.TranslateTo (-100, 0, 1000);    // Move image left
await image.TranslateTo (-100, -100, 1000); // Move image diagonally up and left
await image.TranslateTo (100, 100, 2000);   // Move image diagonally down and right
await image.TranslateTo (0, 100, 1000);     // Move image left
await image.TranslateTo (0, 0, 1000);       // Move image up

在此示例中, Image 在 6 秒 (6000 毫秒) 。 的 Image 转换使用五个动画,运算符 await 指示每个动画按顺序执行。 因此,后续动画方法在上一个方法完成后执行。

复合动画

复合动画是动画的组合,其中两个或多个动画同时运行。 可以通过混合等待和非等待动画来创建复合动画,如以下代码示例所示:

image.RotateTo (360, 4000);
await image.ScaleTo (2, 2000);
await image.ScaleTo (1, 2000);

在此示例中, Image 缩放并同时旋转 4 秒 (4000 毫秒) 。 缩放 Image 使用两个与旋转同时发生的连续动画。 方法 RotateTo 在没有运算符的情况下 await 执行,并立即返回,然后开始第一个 ScaleTo 动画。 await第一个ScaleTo方法调用的运算符会延迟第二ScaleTo个方法调用,直到第一个ScaleTo方法调用完成。 此时, RotateTo 动画已完成一半, Image 并将旋转 180 度。 在最后 2 秒 (2000 毫秒) 期间,第二个 ScaleTo 动画和 RotateTo 动画都完成。

同时运行多个异步方法

staticTask.WhenAnyTask.WhenAll 方法用于同时运行多个异步方法,因此可用于创建复合动画。 这两种方法都返回一个 Task 对象,并接受每个方法返回一个 Task 对象的方法集合。 方法 Task.WhenAny 在其集合中的任何方法完成执行时完成,如以下代码示例所示:

await Task.WhenAny<bool>
(
  image.RotateTo (360, 4000),
  image.ScaleTo (2, 2000)
);
await image.ScaleTo (1, 2000);

在此示例中, Task.WhenAny 方法调用包含两个任务。 第一个任务将图像旋转 4 秒 (4000 毫秒) ,第二个任务将图像缩放到 2 秒 (2000 毫秒) 。 第二个任务完成后, Task.WhenAny 方法调用将完成。 但是,即使 RotateTo 方法仍在运行,第二 ScaleTo 个方法也可以开始。

当集合中的所有方法都已完成时,方法 Task.WhenAll 完成,如以下代码示例所示:

// 10 minute animation
uint duration = 10 * 60 * 1000;

await Task.WhenAll (
  image.RotateTo (307 * 360, duration),
  image.RotateXTo (251 * 360, duration),
  image.RotateYTo (199 * 360, duration)
);

在此示例中, Task.WhenAll 方法调用包含三个任务,每个任务执行超过 10 分钟。 每个旋转 Task 次数不同,360 度 – 307 个旋转, RotateTo251 个旋转, RotateXTo199 个旋转 RotateYTo。 这些值是质数,因此可确保旋转不同步,因此不会导致重复模式。

以下屏幕截图显示了每个平台上正在进行的多次旋转:

复合动画

取消动画

应用程序可以通过调用 CancelAnimations 扩展方法来取消一个或多个动画,如以下代码示例所示:

image.CancelAnimations();

这会立即取消实例上 Image 当前运行的所有动画。

总结

本文演示如何使用 ViewExtensions 类创建和取消动画。 此类提供的扩展方法可用于构造旋转、缩放、平移和淡出 VisualElement 实例的简单动画。