Android當中的動畫4—Property動畫

前言

       博主在前面幾篇博客 當中主要和大家聊了聊Android當中的Tween Animation,但是大家都知道,我們在工作的時候由於Tween Animation的侷限性,我們很少使用它,但是爲什麼我們又要去花時間去了解它呢?因爲我們開發重要的是一種思路,所以我們學習的是它的設計思路,而我們現在使用最多的屬性動畫,也就是在這個思路的基礎上去實現的。如果我們明白了它的設計思路,那麼我們可以不侷限於它的框架,我們可以做自己的動畫。好了,扯歪了,下面我們進入今天我們的要聊的主題,屬性動畫。

正文

       屬性動畫,說白了就和它自己的名字是一樣的,就是對其屬性進行修改,那麼我們不斷地去給某一個屬性值進行遞增的效果,比如我們X的座標,那麼我們的View就會不斷的沿着X的方向運動起來,那麼X的座標就是我們這裏所說的屬性,我們要修改的就是X座標,

       首先我們要明白,屬性動畫實在Android3.0開始纔有的新的動畫框架,因爲Tween 動畫系統已經在android.view.animation中定義了許多的值,所以在此可以使用屬性動畫系統的值。在類Aimator中提供了用於創建動畫的基本結構,但是通常不能直接是使用這個類,因爲其中僅僅提供了一些最基本的功能,必須將其擴展到完全支持的動畫值纔行,下面說說類Animator中的擴展類

ValueAnimator

屬性動畫主要的計算器,也用於計算屬性動畫的值,該子類擁有所有的核心的功能,能夠計算動畫的值並且包含每個動畫,可以設置動畫是否重複,還可以設置自定義類型的功能,(我們可以直接的理解他就是一個計算機,負責計算動畫過程中的過度值)

ObjectAnimator

這個類就是ValueAnimator的子類,允許設置一個目標對象和對象的屬性進行動畫,當計算出一個新的動畫值的時候,會自動的更新相應的屬性,因爲有ValueAnimator的支持,使用ObjectAnimator對象,我們需要關心的也會變得特別的簡單,我們只需要知道我們的起始和結束,就Ok了

AnimatorSet

這個類大家可以理解爲管理每一個動畫執行順序的動畫集合,我們可以去設置動畫的組織方式,使多個動畫相關聯的運動起來,可以給動畫設置一起播放順序播放以及指定延遲播放的效果。

剛剛也說過了,屬性動畫就是不斷地去修改屬性,下面介紹一下常用的屬性都有哪些,

translationX,和 translationY:這兩個屬性控制View對象的在佈局容器當中的位置,注意他是△dx,△dy,就是增量,不是絕對位置

x,y:這兩個屬性控制View對象的在佈局容器當中的位置,它兩個就是絕對位置

rotation、rotationX 和 rotationY: 這三個屬性來控制View對象圍繞支點進行Z,X,Y軸進行旋轉。

scaleX和scaleY:圍繞View對象的支點去做比例的縮放,注意是比例,

alpha:表示View對象的透明度,默認值是1表示不透明,0表示完全透明

pivotX 和 pivotY:就是上述當中的支點位置。

       當然我們也可以自定義屬性,不過我們得給這個屬性提供get,set方法,因爲內部會通過Java反射機制來調用set方法修改對象屬性值


       瞭解過了我們屬性動畫的相關API之後,我們先來做這樣一個小Demo,我們直接去訪問我們View的屬性,讓它隨我們的點擊去直接改變位置



其實我們什麼都沒有做,點擊Button,直接去設置它的內部屬性

    /** 復原 */
    public void enable(View view){
        mImage.setRotationX(0);
        mImage.setRotationY(0);
    }

    /** 點擊旋轉X45° */
    public void animatorX(View view){
        mImage.setRotationX(45f);
    }

    /** 點擊旋轉Y45° */
    public void animatorY(View view){
        mImage.setRotationY(45f);
    }

那不斷地去設置旋轉的值,那麼我們的動畫是不是就可以動起來了,然後我們嘗試使用一個for循環來這麼做,但是我們發現,由於程序太快了我們根本就不能控制,下面我們就介紹另外一個類ValueAnimator,這個類剛剛大體介紹過,就是計算,那他計算什麼呢,他可以在起始值到結束值之間做一個平滑的變換,當然如果你使用了插值器(Interpolators)的話,會根據你插值器裏面定義的方法規則去做一個值得變化。下面我們就使用我們的代碼去研究一下,這個類應該怎麼使用

  ValueAnimator valueAnimator = ValueAnimator.ofInt(1, 100).setDuration(1000);
        valueAnimator.start();
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                int animatedValue = (int) animation.getAnimatedValue();
                mImage.setRotation(animatedValue);
                Log.i("suansuan","animatedValue = " + animatedValue);
            }
        });


I/suansuan( 3373): animatedValue = 1
I/suansuan( 3373): animatedValue = 1
I/suansuan( 3373): animatedValue = 2
I/suansuan( 3373): animatedValue = 4
I/suansuan( 3373): animatedValue = 5
I/suansuan( 3373): animatedValue = 6
I/suansuan( 3373): animatedValue = 7
I/suansuan( 3373): animatedValue = 9
I/suansuan( 3373): animatedValue = 10
I/suansuan( 3373): animatedValue = 12
I/suansuan( 3373): animatedValue = 13
I/suansuan( 3373): animatedValue = 15
I/suansuan( 3373): animatedValue = 17
I/suansuan( 3373): animatedValue = 19
I/suansuan( 3373): animatedValue = 21
I/suansuan( 3373): animatedValue = 23
I/suansuan( 3373): animatedValue = 25
I/suansuan( 3373): animatedValue = 28
I/suansuan( 3373): animatedValue = 30
I/suansuan( 3373): animatedValue = 32
I/suansuan( 3373): animatedValue = 35
I/suansuan( 3373): animatedValue = 37
I/suansuan( 3373): animatedValue = 40
I/suansuan( 3373): animatedValue = 42
I/suansuan( 3373): animatedValue = 45
I/suansuan( 3373): animatedValue = 48
I/suansuan( 3373): animatedValue = 50

我們可以看到在0到50之間做了一個很完美的平滑的增量,而且我們的動畫也很完美的動起來了,我們看到在這裏我們使用了ValueAnimator.AnimatorUpdateListener監聽,這個監聽在動畫的每一個幀上調用在這個監聽使用getAnimatedValue()方法獲取計算出來的值此監聽一般只用於ValueAnimator。另外可能需要在這個方法當中調用View.invalidate()方法來刷新屏幕顯示。

上面就是關於屬性動畫的核心內容,下面我們開看一下屬性動畫的封裝,來進一步瞭解屬性動畫吧,

ObjectAnimator這個類就是直接給一個對象去設置屬性變化,比如以旋轉爲示例,一行代碼解決

 ObjectAnimator.ofFloat(mImage,"rotationY",0f,360f).setDuration(1000).start();



OfFloat()就是對float的類型的值進行變化,相應的有ofInt,ofObject,ofArgb,之類的,而第一個參數就是目標View,第二個參數就是要去操作的屬性值,第三個參數就是起始值,後面的就是結束值。ObjectAnimator就是使用了建造者模式,所以可以無限的使用.XXX().XXX().start();start()方法以後就是沒有返回值,所以不能使用。

如果我們要給我們的view同時開啓縮放和旋轉,怎麼破?如果是在TweenAnimation當中我們會想到AnimationSet,但是在我們的屬性動畫當中,有兩種實現的辦法,分別是PropertyValuesHolder,和AnimatorSet前者像是後者的輕量級實現,而前者只能操作一個View,而後者隨意。我們分別用這兩種辦法去實現剛剛我們的需求

        PropertyValuesHolder rotationX = PropertyValuesHolder.ofFloat("rotationX", 0f,720f);
        PropertyValuesHolder scaleX = PropertyValuesHolder.ofFloat("scaleX", 1f, 0f, 1f);
        PropertyValuesHolder scaleY = PropertyValuesHolder.ofFloat("scaleY", 1f, 0f, 1f);
        ObjectAnimator.ofPropertyValuesHolder(mImage,rotationX,scaleX,scaleY).setDuration(800).start();

我們通過使用PropertyValuesHolder把一種效果進行封裝,而ObjectAnimator相當於是一個總的開關。



下面我們使用AnimatorSet來實現上面我們的需求

<span style="font-size:14px;">        ObjectAnimator rotationX = ObjectAnimator.ofFloat(mImage, "rotationX", 0f, 720f).setDuration(800);
        ObjectAnimator scaleX = ObjectAnimator.ofFloat(mImage, "scaleX", 1f, 0f, 1f).setDuration(800);
        ObjectAnimator scaleY = ObjectAnimator.ofFloat(mImage, "scaleY", 1f, 0f, 1f).setDuration(800);

        AnimatorSet animatorSet = new AnimatorSet();
        animatorSet.playTogether(rotationX,scaleX,scaleY);
        animatorSet.start();</span>

效果和上面是一樣的所以在這裏博主就不向各位展示了

我們發現,我們ObjectAnimator去組織PropertyValuesHolder節點,而我們的AnimatorSet去操作ObjectAnimator節點,如果我們在以後的開發工作當中,我們去組合使用,那麼可以實現很炫的效果呢。


如果我們要求先執行旋轉,再同時縮放Y,縮放X,怎麼破?

其實這纔是這個AnimatorSet的核心功能,那就是可以去組織動畫播放的順序,


        ObjectAnimator rotationX = ObjectAnimator.ofFloat(mImage, "rotationX", 0f, 720f).setDuration(800);
        ObjectAnimator scaleX = ObjectAnimator.ofFloat(mImage, "scaleX", 1f, 0f, 1f).setDuration(800);
        ObjectAnimator scaleY = ObjectAnimator.ofFloat(mImage, "scaleY", 1f, 0f, 1f).setDuration(800);

        AnimatorSet animatorSet = new AnimatorSet();
//        animatorSet.playTogether(rotationX,scaleX,scaleY);
        animatorSet.play(scaleX).after(rotationX).with(scaleY);
        animatorSet.start();

AnimatorSet,提供一些組織順序的方法,play().after().befor().with(),用戶比較簡單,在這裏博主就不多說了



最後我們來看看屬性動畫的監聽,我們的屬性動畫的監聽

ObjectAnimator rotationX = ObjectAnimator.ofInt(mImage, "rotationX", 0, 720).setDuration(800);
        
        //我們可以使用AnimatorListener實現類
        rotationX.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animator) {
                //動畫開始
            }

            @Override
            public void onAnimationEnd(Animator animator) {
                //動畫結束
            }

            @Override
            public void onAnimationCancel(Animator animator) {
                //動畫撤銷
            }

            @Override
            public void onAnimationRepeat(Animator animator) {
                //動畫重新播放
            }
        });
        
        //使用AnimatorListener的實現類AnimatorListenerAdapter,來捕捉我們需要的回調方法
        rotationX.addListener(new AnimatorListenerAdapter() {

            @Override
            public void onAnimationStart(Animator animation) {
                
            }
        });



















發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章