天天看點

第二十二章:動畫(十七)

子動畫

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。

繼續閱讀