中的简单动画 Xamarin.Forms
ViewExtensions 类提供可用于构造简单动画的扩展方法。 本文演示如何使用 ViewExtensions 类创建和取消动画。
类 ViewExtensions
提供以下可用于创建简单动画的扩展方法:
CancelAnimations
取消任何动画。FadeTo
对 的Opacity
属性进行VisualElement
动画处理。RelScaleTo
将动画增量增加或减少应用于Scale
的VisualElement
属性。RotateTo
对 的Rotation
属性进行VisualElement
动画处理。RelRotateTo
将动画增量增加或减少应用于Rotation
的VisualElement
属性。RotateXTo
对 的RotationX
属性进行VisualElement
动画处理。RotateYTo
对 的RotationY
属性进行VisualElement
动画处理。ScaleTo
对 的Scale
属性进行VisualElement
动画处理。ScaleXTo
对 的ScaleX
属性进行VisualElement
动画处理。ScaleYTo
对 的ScaleY
属性进行VisualElement
动画处理。TranslateTo
对TranslationX
的 和TranslationY
属性进行VisualElement
动画处理。
默认情况下,每个动画需要 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,从而防止其他旋转。
以下屏幕截图显示了每个平台上正在进行的轮换:
相对旋转
下面的代码示例演示如何使用 RelRotateTo
方法以增量方式增加或减少 Rotation
的 Image
属性:
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) 。 这会导致将图像的大小扩大为其大小的两倍。
以下屏幕截图显示了每个平台上正在进行的缩放:
相对缩放
下面的代码示例演示如何使用 RelScaleTo
方法对 的 属性进行Image
动画处理Scale
:
await image.RelScaleTo (2, 2000);
此代码通过在 2 秒 (2000 毫秒) 缩放到其大小的两倍来对实例进行动画 Image
处理。 方法 RelScaleTo
获取动画开头的当前 Scale
属性值,然后从该值缩放到值及其第一个参数 (2) 。 这可确保每个动画始终从起始位置缩放为 2。
使用定位点进行缩放和旋转
AnchorX
和 AnchorY
属性设置 和 Scale
属性的缩放或旋转Rotation
中心。 因此,它们的值也会影响 RotateTo
和 ScaleTo
方法。
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
动画都完成。
同时运行多个异步方法
static
Task.WhenAny
和 Task.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 个旋转, RotateTo
251 个旋转, RotateXTo
199 个旋转 RotateYTo
。 这些值是质数,因此可确保旋转不同步,因此不会导致重复模式。
以下屏幕截图显示了每个平台上正在进行的多次旋转:
取消动画
应用程序可以通过调用 CancelAnimations
扩展方法来取消一个或多个动画,如以下代码示例所示:
image.CancelAnimations();
这会立即取消实例上 Image
当前运行的所有动画。
总结
本文演示如何使用 ViewExtensions
类创建和取消动画。 此类提供的扩展方法可用于构造旋转、缩放、平移和淡出 VisualElement
实例的简单动画。