.NET 多平台应用 UI (.NET MAUI)
Animation
类是所有 .NET MAUI 动画的构建基块,类中的
ViewExtensions
扩展方法创建一个或多个
Animation
对象。
创建
Animation
对象时必须指定多个参数,包括要进行动画处理的属性的开始和结束值,以及更改属性值的回调。 对象
Animation
还可以维护可运行和同步的子动画集合。 有关详细信息,请参阅
子动画
。
通过调用
Commit
方法,可以运行使用
Animation
类创建的动画,该类可能包含子动画,也可能不包含子动画。 此方法指定动画的持续时间,以及控制是否重复动画的其他项的回调。
类
Animation
具有一个
IsEnabled
属性,可以检查该属性以确定动画是否已被操作系统禁用,例如在激活节能模式时。
创建
Animation
对象时,通常至少需要三个参数,如以下代码示例所示:
var animation = new Animation(v => image.Scale = v, 1, 2);
在此示例中,实例属性 Scale 的 Image 动画从值 1 到值 2 定义。 动画值将传递到指定为第一个参数的回调,其中它用于更改属性的值 Scale 。
动画通过调用 Commit 方法启动:
animation.Commit(this, "SimpleAnimation", 16, 2000, Easing.Linear, (v, c) => image.Scale = 1, () => true);
方法 Commit 不返回 Task
对象。 相反,通知是通过回调方法提供的。
方法中 Commit 指定了以下参数:
第一个参数 (owner
) 标识动画的所有者。 这可以是应用动画的视觉元素,也可以是另一个视觉元素,例如页面。
第二个参数 (name
) 用名称标识动画。 该名称与所有者组合在一起以唯一标识动画。 然后,可以使用此唯一标识来确定动画是 () AnimationIsRunning 运行,还是 () AbortAnimation 取消动画。
第三个参数 (rate
) 指示每次调用构造函数中 Animation 定义的回调方法之间的毫秒数。
第四个参数 (length
) 指示动画的持续时间(以毫秒为单位)。
第五个参数 (Easing) 定义要在动画中使用的缓动函数。 或者,缓动函数可以指定为构造函数的参数 Animation 。 有关缓动函数的详细信息,请参阅 缓动函数。
) (finished
的第六个参数是将在动画完成时执行的回调。 此回调采用两个参数,第一个参数指示最终值,第二个参数是设置为 bool
true
(如果动画已取消)。 或者, finished
可以将回调指定为构造函数的参数 Animation 。 但是,对于单个动画,如果在finished
构造函数和 Commit 方法中都Animation指定了回调,则只会执行 方法中指定的Commit回调。
) (repeat
第七个参数是允许重复动画的回调。 它在动画结束时调用,返回 true
指示应重复动画。
在上面的示例中,整体效果是创建一个动画,使用Linear缓动函数将实例的属性Image从 1 增加到 Scale 2,超过 2 秒 (2000 毫秒) 。 每次动画完成时,其 Scale 属性将重置为 1,动画将重复。
通过为每个动画创建一个 Animation 对象,然后在每个动画上调用 Commit 方法,可以构造相互独立运行的并发动画。
类 Animation 还支持子动画,这些动画是 Animation 其他 Animation 对象作为子级添加到的对象。 这样就可以运行和同步一系列动画。 以下代码示例演示如何创建和运行子动画:
var parentAnimation = new Animation();
var scaleUpAnimation = new Animation(v => image.Scale = v, 1, 2, Easing.SpringIn);
var rotateAnimation = new Animation(v => image.Rotation = v, 0, 360);
var scaleDownAnimation = new Animation(v => image.Scale = v, 2, 1, Easing.SpringOut);
parentAnimation.Add(0, 0.5, scaleUpAnimation);
parentAnimation.Add(0, 1, rotateAnimation);
parentAnimation.Add(0.5, 1, scaleDownAnimation);
parentAnimation.Commit(this, "ChildAnimations", 16, 4000, null, (v, c) => SetIsEnabledButtonState(true, false));
或者,可以更简洁地编写代码示例:
new Animation
{ 0, 0.5, new Animation (v => image.Scale = v, 1, 2) },
{ 0, 1, new Animation (v => image.Rotation = v, 0, 360) },
{ 0.5, 1, new Animation (v => image.Scale = v, 2, 1) }
}.Commit (this, "ChildAnimations", 16, 4000, null, (v, c) => SetIsEnabledButtonState (true, false));
在这两个示例中,都创建了一个父 Animation 对象,然后向其添加其他 Animation 对象。 方法的前两个参数 Add 指定何时开始和完成子动画。 参数值必须介于 0 和 1 之间,并表示指定子动画将处于活动状态的父动画中的相对周期。 因此,在此示例中, scaleUpAnimation
将在动画的前半部分处于活动状态, scaleDownAnimation
在动画的后半部分将处于活动状态,而 rotateAnimation
将在整个持续时间内处于活动状态。
此示例的总体效果是动画在 4 秒 (4000 毫秒) 发生。 将 scaleUpAnimation
属性从 Scale 1 到 2(超过 2 秒)进行动画处理。 scaleDownAnimation
然后,将Scale属性从 2 到 1(超过 2 秒)进行动画处理。 当这两个缩放动画都发生时,将 rotateAnimation
属性从 0 到 360(超过 4 秒)进行 Rotation 动画处理。 这两个缩放动画还使用缓动函数。 SpringIn缓动函数会导致Image实例在变大之前先收缩,缓SpringOut动函数会导致 Image 在完整动画结束时小于其实际大小。
使用子动画的对象与不使用子动画的对象之间存在 Animation 许多差异:
使用子动画时,子动画的 finished
回调指示子动画完成的时间, finished
传递给 方法的 Commit 回调指示整个动画完成的时间。
使用子动画时,从 方法的repeat
Commit回调返回true
不会导致动画重复,但动画将继续运行,且没有新值。
在 方法中包含 Commit 缓动函数,并且缓动函数返回大于 1 的值时,动画将终止。 如果缓动函数返回小于 0 的值,则该值被固定为 0。 若要使用返回小于 0 或大于 1 的值的缓动函数,必须在子动画之一(而不是 方法)中 Commit 指定它。
类 Animation 还包括 WithConcurrent 可用于向父 Animation 对象添加子动画的方法。 但是,它们的 begin
和 finish
参数值不限制为 0 到 1,但只有对应于 0 到 1 范围的子动画部分将处于活动状态。 例如,如果 WithConcurrent 方法调用定义了一个子动画,该动画面向 Scale 从 1 到 6 的属性,但 begin
和 finish
值为 -2 和 3, begin
则值 -2 对应于 Scale 值 1, finish
值 3 对应于 Scale 值 6。 由于超出范围 0 和 1 的值在动画中不起任何作用, Scale 因此将仅对属性进行 3 到 6 的动画处理。
应用可以通过调用 AbortAnimation 扩展方法来取消自定义动画:
this.AbortAnimation ("SimpleAnimation");
由于动画由动画所有者和动画名称的组合唯一标识,因此必须指定在运行动画时指定的所有者和名称才能取消动画。 因此,此示例将立即取消页面拥有的名为 SimpleAnimation
的动画。
创建自定义动画
到目前为止,此处显示的示例演示了使用 类中的方法同样可以实现的 ViewExtensions 动画。 但是, 类的优点 Animation 是它有权访问回调方法,该方法在动画值更改时执行。 这允许回调实现任何所需的动画。 例如,以下代码示例通过将页面的 属性设置为 Color 方法Color.FromHsla
创建的值(色调值范围为 0 到 1)来对页面的 属性进行动画BackgroundColor处理:
new Animation (callback: v => BackgroundColor = Color.FromHsla (v, 1, 0.5),
start: 0,
end: 1).Commit (this, "Animation", 16, 4000, Easing.Linear, (v, c) => BackgroundColor = Colors.Black);
生成的动画提供通过彩虹颜色推进页面背景的外观。
创建自定义动画扩展方法
类中的 ViewExtensions 扩展方法将属性从其当前值动画转换为指定值。 例如,这会使创建动画方法变得困难, ColorTo
该动画方法可用于对颜色从一个值到另一个值进行动画处理。 这是因为不同的控件具有 类型 Color不同的属性。 VisualElement虽然 类定义BackgroundColor属性,但这并不总是要进行动画处理所需的Color
属性。
此问题的解决方案是不让 ColorTo
方法面向特定 Color
属性。 相反,可以使用回调方法编写,该方法将内 Color 插值传递回调用方。 此外, 方法将采用 start 和 end Color 参数。
方法 ColorTo
可以作为扩展方法实现,该扩展方法使用 Animate 类中的 AnimationExtensions 方法来提供其功能。 这是因为 方法 Animate 可用于目标不是 类型 double
的属性,如以下代码示例所示:
public static class ViewExtensions
public static Task<bool> ColorTo(this VisualElement self, Color fromColor, Color toColor, Action<Color> callback, uint length = 250, Easing easing = null)
Func<double, Color> transform = (t) =>
Color.FromRgba(fromColor.Red + t * (toColor.Red - fromColor.Red),
fromColor.Green + t * (toColor.Green - fromColor.Green),
fromColor.Blue + t * (toColor.Blue - fromColor.Blue),
fromColor.Alpha + t * (toColor.Alpha - fromColor.Alpha));
return ColorAnimation(self, "ColorTo", transform, callback, length, easing);
public static void CancelAnimation(this VisualElement self)
self.AbortAnimation("ColorTo");
static Task<bool> ColorAnimation(VisualElement element, string name, Func<double, Color> transform, Action<Color> callback, uint length, Easing easing)
easing = easing ?? Easing.Linear;
var taskCompletionSource = new TaskCompletionSource<bool>();
element.Animate<Color>(name, transform, callback, 16, length, easing, (v, c) => taskCompletionSource.SetResult(c));
return taskCompletionSource.Task;
方法 Animate 需要一个 transform
参数,即回调方法。 此回调的输入始终 double
为 0 到 1。 因此,在此示例中, ColorTo
方法定义其自己的转换,该转换 Func
接受 double
范围从 0 到 1,并返回与 Color 该值对应的值。 该值Color是通过内插提供的Color两个参数的 Red
、Green
、 Blue
和 Alpha
值来计算的。 然后,该值 Color 将传递给回调方法,以应用于属性。 此方法允许 ColorTo
方法对任何指定的 Color 属性进行动画处理:
await Task.WhenAll(
label.ColorTo(Colors.Red, Colors.Blue, c => label.TextColor = c, 5000),
label.ColorTo(Colors.Blue, Colors.Red, c => label.BackgroundColor = c, 5000));
await this.ColorTo(Color.FromRgb(0, 0, 0), Color.FromRgb(255, 255, 255), c => BackgroundColor = c, 5000);
await boxView.ColorTo(Colors.Blue, Colors.Red, c => boxView.Color = c, 4000);
在此代码示例中ColorTo
, 方法对 的 和 BackgroundColor 属性Label进行动画处理TextColor
, BackgroundColor 页面的 属性和 Color
的 BoxView属性。