第二十二章:动画(十七)-云栖社区-阿里云

子动画ConcurrentAnimations中的前两个示例是单个动画。 Animation类还支持子动画,这就是标记为“Animation 3”的Button的处理程序。 它首先使用无参数构造函数创建父动画对象。

子动画
ConcurrentAnimations中的前两个示例是单个动画。 Animation类还支持子动画,这就是标记为“Animation 3”的Button的处理程序。 它首先使用无参数构造函数创建父动画对象。 然后它创建两个额外的Animation对象,并使用Add和Insert方法将它们添加到父Animation对象:

public partial class ConcurrentAnimationsPage : ContentPage
{
    __
    void OnButton3Clicked(object sender, EventArgs args)
    {
        Button button = (Button)sender;
        // Create parent animation object.
        Animation parentAnimation = new Animation();
        // Create "up" animation and add to parent.
        Animation upAnimation = new Animation(
            v => button.Scale = v,
            1, 5, Easing.SpringIn, 
            () => Debug.WriteLine("up finished"));
        parentAnimation.Add(0, 0.5, upAnimation);
        // Create "down" animation and add to parent.
        Animation downAnimation = new Animation(
            v => button.Scale = v,
            5, 1, Easing.SpringOut, 
            () => Debug.WriteLine("down finished"));
        parentAnimation.Insert(0.5, 1, downAnimation);
        // Commit parent animation.
        parentAnimation.Commit(
            this, "Animation3", 16, 5000, null, 
            (v, c) => Debug.WriteLine("parent finished: {0} {1}", v, c));
        }
    __
}

这些Add和Insert方法基本相同,在实际使用中是可以互换的。唯一的区别是Insert返回父动画对象而Add不返回。
这两种方法都需要两个类型为double的参数,名称为beginAt和finishAt。这两个参数必须介于0和1之间,而finishAt必须大于beginAt。这两个参数表示这些特定子动画活动的总动画中的相对时间段。
总动画长达五秒钟。这是Commit方法中5000的参数。第一个子动画将Scale属性从1设置为5. beginAt和finishAt参数分别为0和0.5,这意味着此子动画在整个动画的前半部分处于活动状态 - 即在前2.5秒内处于活动状态。第二个子动画将Scale属性从5返回到1. beginAt和finishAt参数分别为0.5和1,这意味着此动画发生在整个五秒动画的后半部分。
结果是Button在2.5秒内缩放到其大小的五倍,然后在最后的2.5秒内缩小到1。 但请注意两个子动画上设置的两个缓动函数。 Easing.SpringIn对象导致Button在变大之前最初缩小,而Easing.SpringOut函数也会导致Button在完整动画结束时变得小于其实际大小。
正如您在单击按钮以运行此代码时所看到的,现在调用所有已完成的回调。 这是将Animation类用于单个动画并使用它的一个区别
儿童动画。 子动画的完成回调指示该特定子项何时完成,并且传递给Commit方法的完成回调指示整个动画何时完成。
使用儿童动画时还有两个不同之处:

  • 使用子动画时,从Commit方法的重复回调返回true不会导致动画重复,但动画将继续运行而没有新值。
  • 如果在Commit方法中包含Easing函数,并且Easing函数返回大于1的值,则动画将在该点终止。 如果Easing函数返回小于0的值,则该值被钳制为等于0。

如果要使用返回小于0或大于1的值的Easing函数(例如,Easing.SpringIn或Easing.SpringOut函数),请在一个或多个子动画中指定它,如示例所示, 而不是Commit方法。
C#编译器将实现IEnumerable的类的Add方法识别为集合初始值设定项。 若要将动画语法保持最小,可以使用一对花括号跟随父动画对象上的new运算符,以使用子项初始化内容。 这些外部花括号内的每对花括号都包含Add方法的参数。 这是一个有三个孩子的动画:

public partial class ConcurrentAnimationsPage : ContentPage
{
    __
    void OnButton4Clicked(object sender, EventArgs args)
    {
        Button button = (Button)sender;
        new Animation
        {
            { 0, 0.5, new Animation(v => button.Scale = v, 1, 5) },
            { 0.25, 0.75, new Animation(v => button.Rotation = v, 0, 360) },
            { 0.5, 1, new Animation(v => button.Scale = v, 5, 1) }
        }.Commit(this, "Animation4", 16, 5000);
    }
    __
}

另请注意,Commit直接在Animation构造函数上调用。这和您编写此代码一样简洁。
这些隐式Add方法的前两个参数指示子项处于活动状态的整个父动画中的位置。第一个子项为“缩放”属性设置动画,并在父动画的前半部分处于活动状态,最后一个子项也为“缩放”属性设置动画,并在父动画的后半部分处于活动状态。这与前一个例子相同。但现在还有一个Rotation属性的动画,其开始和结束值分别为0.25和0.75。此旋转动画在第一个“缩放”动画的中间开始,并在第二个“缩放”动画的中途结束。这就是儿童动画可以重叠的方式。
Animation类还包括两个名为WithConcurrent的方法,用于将子动画添加到父动画对象。 这些类似于Add和Insert方法,除了beginAt和finishAt参数(或者在其中一个WithConcurrent方法中调用它们的开始和结束)不限制在0到1的范围内。但是,只有那个部分 对应于0到1范围的子动画将处于活动状态。
例如,假设您调用WithConcurrent来定义一个子动画,该动画将Scale属性从1到4,但是beginAt参数为-1,finishAt参数为2。
beginAt值-1对应Scale值1,finishAt值2对应Scale值4,但0和1范围之外的值不在动画中起作用,因此Scale属性 只会动画从2到3。