2017/8/8

Xamarin.Forms 教學系列文(二十二)Animation - 物件動畫


學習目標
  • Animation - RotateTo, ScaleTo, Translateto, FadeTo, LayoutTo
  • 第二次點擊失效原因與解法
  • Easing Function - 動畫曲線

Xamarin.Forms 對物件的形狀位置變化,除了像上一章節手動更改物件的屬性,來放大縮小移動位置。

同時也提供了一些簡易的 動畫方法,如漸漸消失,移動到某處,變大,旋轉..

動畫方法目前不支援寫在 XAML,全部都要用 C#

直接看一支簡單的範例:

XAML 內只有一顆按鈕:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="AnimationTryout.AnimationTryoutPage">
    
    <Button x:Name="button" 
            Text="Tap Me!" 
            FontSize="Large" 
            HorizontalOptions="Center" 
            VerticalOptions="Center" 
            Clicked="OnButtonClicked" />
    
</ContentPage>
.cs
讓按鈕旋轉 360 度:
public partial class AnimationTryoutPage : ContentPage
{
    public AnimationTryoutPage()
    {
        InitializeComponent();
    }

    void OnButtonClicked(object sender, EventArgs args)
    {
        button.RotateTo(360);
    }
}

RotateTo 方法就是一個讓物件可以旋轉的動畫方法

當旋轉完,要按下第二次時會發現不轉了!!! 怎麼了你累了...?

是因為,我們第一次讓按鈕 從 0 轉到 360 後,其值會保持在 360
所以第二次按下去時,程式會要求按鈕 從 360 轉到 360 ,如此一來就沒有反應

遇到第二次不能的問題,可以改用 RelRotateTo() 這方法,
這方法會在每次動畫結束時,重新設定其物件參數值 ( Rotation 回到 0 )

總之,第二次執行復活

當然也可以在每次執行動畫前手動初始化
        void OnButtonClicked(object sender, EventArgs args)
        {
            button.Rotation = 0; 
           button.RotateTo(360, 2000);
        }

*註:動畫執行的時間可自行設定
void OnButtonClicked(object sender, EventArgs args)
{
    //提高到 2000 毫秒內轉完,一般預設是 250 毫秒
    button.RotateTo(360, 2000);
}

連續動畫

由於動畫方法是屬於 非同步方法,故能加上 await 讓每一動畫去等待上一動畫結束。
        async void OnButtonClicked(object sender, EventArgs args)
        {
            await button.RotateTo(90, 250);
            await button.RotateTo(-90, 500);
            await button.RotateTo(0, 250);
        }

合併動畫

除了 RotateTo 外, Xamarin.Forms 還提供了 ScaleTo、TranslateTo、FadeTo 和 LayoutTo 等動畫方法可以使用。

假設我們現在要將兩個動畫混合在一起,例如 旋轉同時也要放大縮小

可以使用 Task 提供的兩個方法來處理,Task.WhenAllTask.WhenAny
這兩個方法能夠放入數個非同步方法一起執行

Task.WhenAll 
等全部非同步方法執行完才離開

Task.WhenAny 
當有任一個非同步方法執行完畢就會離開

上範例:
        async void OnButtonClicked(object sender, EventArgs args)
        {
            button.Rotation = 0;

           //當放大結束時就會去執行縮小
            await Task.WhenAny
                (
                    button.RotateTo(360, 2000), 
                    button.ScaleTo(5, 1000)
                );

            await button.ScaleTo(1, 1000);
        }


* 註1:
做 RotateTo 和 ScaleTo 時,
可以設定 錨定點( AnchorX & AnchorY ) 屬性 ,去釘住物件要旋轉或放大的固定位置

* 註2:
如果我們要取消動畫,可以用這個方法:
ViewExtensions.CancelAnimations(button);

Easing Function - 動畫曲線
        async void OnButtonClicked(object sender, EventArgs args)
        {
            await button.RotateTo(90, 250);
            await button.RotateTo(-90, 500);
            await button.RotateTo(0, 250);
        }

如果你有執行以上程式,會覺得其動作相當生硬且機械感十足...

為此,Xamarin.Forms 很貼心的提供了好幾組動畫曲線,加上去後可以讓動畫看起來很圓滑或是活潑...

試試看以下程式,將 Easing function 加入動畫:
        async void OnButtonClicked(object sender, EventArgs args)
        {
            await button.RotateTo(90, 250, Easing.SinOut);
            await button.RotateTo(-90, 500, Easing.SinInOut);
            await button.RotateTo(0, 250, Easing.SinIn);
        }


眼睛好的會發現動作較圓滑了...

Easing function 全部有五個類別:
  1. Linear - 預設
  2. SinIn, SinOut, and SinInOut
  3. CubicIn, CubicOut, and CubicInOut
  4. BounceIn and BounceOut
  5. SpringIn and SpringOut

原文書提供執行時的曲線,但說真的,乍看下不知道這些圖在衝殺虫…

搭配動畫來看會更清楚,以下都用旋轉來做範例

緩和系列 - SinIn, SinOut, and SinInOut



反差大系列 - CubicIn, CubicOut, and CubicInOut


彈跳系列 - BounceIn, BounceOut



倒退嚕系列 - SpringIn, SpringOut


LayoutTo

最後要提一下最奇特動畫方法,因為要傳入的參數居然是 Rectangle

通常在 AbsoluteLayout 使用,並將含有 x, y , width, height 四個數值的 Rectangle 傳入,直接控制物件要做變化的四個屬性。

我們不會在 StackLayout 或 Grid 使用 LayoutTo,因為以上兩個容器都會自動排版或調整子元素的位置




2 則留言:

  1. 你是我见过唯一一个写教程这么详细和用心的人,你的态度值得尊敬。小弟佩服。也希望罗大神以后在Xamarin方面能多多指教。先谢谢了

    回覆刪除
    回覆
    1. 感謝支持,每篇文章都花了許多時間去閱讀原文教學,翻譯,編排和修改,好好珍惜就好哈哈。當然也是希望能用中文推廣這項技術

      刪除