1. 程式人生 > >Android動畫之屬性動畫基礎用法

Android動畫之屬性動畫基礎用法

在上一篇Android動畫基礎之補間動畫與逐幀動畫 ,我們複習了Android的基礎動畫Tweened Animation、Frame Animation,同時指出他們的缺陷,改變是View的顯示效果而不是View本身的屬性,還有我們不多不少會看多人家的APP有一些很酷炫的動畫效果,但是我們Android本身的基礎動畫是用硬編碼方式完成的,功能很有限,擴充套件性很差,無法滿足的現今的產品需求。因為我們今次的主角要出現了,Property Animation屬性動畫。

屬性動畫(Property Animation) 屬性動畫是在Android3.0中引進的,它更改的是物件的實際屬性,在基礎動畫中改變的是View的繪製效果,真正的View的屬性是沒有改變的,而屬性動畫,改變的是物件的實際屬性,能編寫各種滿足我們需求的動畫。

Property Animation相關類:

  • ValueAnimator:包括Property Animation動畫的所有核心功能,如動畫時間、開始、結束屬性值。

  • ObjectAnimator:繼承於ValueAnimator,要指定一個物件及該物件的一個屬性,當屬性值計算完成時自動設定為改該物件的相對屬性。實際應用中一般會用ObjectAnimator來改變某一物件的某一屬性。

  • AnimatorSet:提供了一個把多個動畫組合成一個組合的機制。

  • AnimatorInflater:用於載入屬性動畫的xml檔案

  • TypeEvalutors:型別估值,主要用於設定動畫操作屬性的值

Android提供了以下幾個evalutor:

IntEvaluator:屬性的值型別為int;
FloatEvaluator:屬性的值型別為float;
ArgbEvaluator:屬性的值型別為十六進位制顏色值;

  • TimeInterplator:時間差值,定義了動畫屬性值變化的方式,在Property Animation中是TimeInterplator,在View Animation中是Interplator,這兩個是一樣的,在3.0之前只有Interplator,3.0之後實現程式碼轉移至了 TimeInterplator。Interplator繼承自TimeInterplator,內部沒有任何其他程式碼。

ValueAnimator

  • 呼叫ValueAnimator提供的靜態方法例項化ValueAnimator物件,如ofArgb(int… values)、ofFloat(float… values)等,並設定目標屬性的屬性名、初始值、結束值等;
  • 呼叫ValueAnimator.addUpdateListener(AnimatorUpdateListener listener)為ValueAnimator物件設定屬性變化的監聽器;
  • 建立自定義的Interpolator,呼叫setInterpolator(TimeInterpolator value)為ValueAniamtor設定自定義的Interpolator;
  • 建立自定義的TypeEvaluator,呼叫setEvaluator(TypeEvaluator value)為ValueAnimator設定自定義的TypeEvaluator;
  • 在AnimatorUpdateListener中的實現方法為目標物件的屬性設定計算好的屬性值;
  • 設定動畫的持續時間、是否重複及重複次數等屬性;
  • 對ValueAnimator設定目標物件並開始執行動畫。

下面我們簡單地使用一下ValueAnimator:

                ValueAnimator valueAnimator = ValueAnimator.ofInt(0, 100);
                valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                    @Override
                    public void onAnimationUpdate(ValueAnimator animation) {
                        Log.i("onAnimationUpdate", "onAnimationUpdate: " + animation.getAnimatedValue());
                    }
                });
                valueAnimator.setDuration(200);
                valueAnimator.start();

上面程式碼我們是用ofInt()方法,帶的引數是0,100,然後通過用AnimatorUpdateListener設定動畫監聽,如下圖看到動畫的值在200毫秒內從0到100打印出來。

這裡寫圖片描述

ObjectAnimator

我們接著學習一下ObjectAnimator這動畫實現類的用法,首先ObjectAnimator繼承ValueAnimator,那就說ObjectAnimator可以重寫ValueAnimator父類提供的方法。在實際開發中,我們更多地使用ObjectAnimator來實現我們需要的動畫效果。在之前我們說過ViewAnimation的缺點,所以Android3.0中為View增加了一些新屬性以及對應的getter、setter方法。那我們來看一下這些新增的動畫屬性:

1.translationX和translationY:這兩個屬性控制著View的螢幕位置座標變化量,以layout容器的左上角為座標原點;
2.rotation、rotationX 和 rotationY:這三個屬性控制著 2D 旋轉角度(rotation屬性)和圍繞某樞軸點的 3D 旋轉角度;
3.scaleX、scaleY:這兩個屬性控制著 View 圍繞某樞軸點的 2D 縮放比例;
4.pivotX 和 pivotY: 這兩個屬性控制著樞軸點的位置,前述的旋轉和縮放都是以此點為中心展開的,預設的樞軸點是 View 物件的中心點;
5.x 和 y:這是指 View 在容器內的最終位置,等於 View 左上角相對於容器的座標加上 translationX 和 translationY 後的值;
alpha:表示 View 的 alpha 透明度。預設值為 1 (不透明),為 0 則表示完全透明(看不見);

然而用法跟ValueAnimator大同小異,我們通過例子來說明:

ObjectAnimator animator = ObjectAnimator.ofFloat(imageView, "rotation", 0f, 360f);  
animator.setDuration(1000);  
animator.start(); 

感覺是沒區別啊,我們ObjectAnimator其實是對繼承了View控制元件的屬性setter、getter方法進行修改值的。ObjectAnimator可以在屬性上進行操作,而ValueAnimator並沒有在屬性上做操作,ObjectAnimator對一些簡單的動畫使用起來比較方便,而ValueAnimator就比較靈活,之後我們會詳細講解。

組合動畫AnimatorSet

組合動畫,PropertyAnimation是用到AnimatorSet這個類,該類提供一個play()的方法,還有提供:

  • after(Animator anim) 將現有動畫插入到傳入的動畫之後執行
  • after(long delay) 將現有動畫延遲指定毫秒後執行
  • before(Animator anim) 將現有動畫插入到傳入的動畫之前執行
  • with(Animator anim) 將現有動畫和傳入的動畫同時執行
                ObjectAnimator moveIn = ObjectAnimator.ofFloat(image, "translationX", -100f, 0f);
                ObjectAnimator rotate = ObjectAnimator.ofFloat(image, "rotation", 0f, 180f);
                ObjectAnimator fadeInOut = ObjectAnimator.ofFloat(image, "alpha", 1f, 0f, 1f);
                AnimatorSet animSet = new AnimatorSet();
                animSet.play(rotate).with(fadeInOut).after(moveIn);
                animSet.setDuration(2000);
                animSet.start();

感覺比較基礎的用法。

XML編寫動畫

用XML來編寫描述我們需要的動畫可能是我們最常用的一種做法,所以PropertyAnimation肯定也提供這種XML的方式來實現功能。在XML我們常用到的三個標籤:

  • <animator> 對應程式碼中的ValueAnimator
  • <objectAnimator> 對應程式碼中的ObjectAnimator
  • <set> 對應程式碼中的AnimatorSet

標籤是可以巢狀的。
標籤的android:ordering屬性規定了這個set中的動畫的執行順序。該屬性值預設是together (default)。

首先要在res目錄下面新建一個animator資料夾,然後我們的XML程式碼的實現如下:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:ordering="sequentially">
    <objectAnimator
        android:duration="2000"
        android:propertyName="translationX"
        android:valueFrom="-500"
        android:valueTo="0"
        android:valueType="floatType" />

    <set android:ordering="together">
        <objectAnimator
            android:duration="3000"
            android:propertyName="rotation"
            android:valueFrom="0"
            android:valueTo="360"
            android:valueType="floatType" />

        <set android:ordering="sequentially">
            <objectAnimator
                android:duration="1500"
                android:propertyName="alpha"
                android:valueFrom="1"
                android:valueTo="0"
                android:valueType="floatType" />
            <objectAnimator
                android:duration="1500"
                android:propertyName="alpha"
                android:valueFrom="0"
                android:valueTo="1"
                android:valueType="floatType" />
        </set>
    </set>
</set>

XML檔案寫好,那麼我們用Java程式碼將對於的動畫載入並啟動。

                Animator animator = AnimatorInflater.loadAnimator(this, R.animator.anim_set);
                animator.setTarget(image);
                animator.start();

Animator監聽器

在動畫的繪製中,肯定少不了我們的動畫監聽事件來處理各種需求和邏輯,Animator類當中提供了一個addListener()方法:

               mAnimator.addListener(new Animator.AnimatorListener() {
                    @Override
                    public void onAnimationStart(Animator animation) {

                    }

                    @Override
                    public void onAnimationEnd(Animator animation) {

                    }

                    @Override
                    public void onAnimationCancel(Animator animation) {

                    }

                    @Override
                    public void onAnimationRepeat(Animator animation) {

                    }
                });

可以看到,我們需要實現介面中的四個方法,onAnimationStart()方法會在動畫開始的時候呼叫,onAnimationRepeat()方法會在動畫重複執行的時候呼叫,onAnimationEnd()方法會在動畫結束的時候呼叫,onAnimationCancel()方法會在動畫被取消的時候呼叫。

但是有些時候我們可能只想要監聽動畫開始這一個事件,那麼每次都要將四個介面全部實現一遍就顯得非常繁瑣。所以Android提供了一個介面卡類,叫作AnimatorListenerAdapter,使用這個類就可以解決掉實現介面繁瑣的問題了,如下所示:

                mAnimator.addListener(new AnimatorListenerAdapter() {
                    @Override
                    public void onAnimationStart(Animator animation) {
                        super.onAnimationStart(animation);
                    }
                });

好的,通過本篇文章的學習,我想大家已經對屬性動畫的基本API用法已經有了一定的認識,並把最常用的一些功能都掌握好了。接下來下一篇我們繼續深入學習PropertyAnimation。