1. 程式人生 > >Android屬性動畫(ObjectAnimator、PropertyValuesHolder、ValueAnimator、AnimatorSet)

Android屬性動畫(ObjectAnimator、PropertyValuesHolder、ValueAnimator、AnimatorSet)

Android屬性動畫

  在Animator 框架中,使用最多的就是AnimatorSet和ObjectAnimator配合,使用ObjectAnimator進行更加精細的控制,只控制一個物件的一個屬性值,爾斯用多個ObjectAnimator組合到AnimatorSet形成一個動畫。而且ObjectAnimator能夠自動驅動,可以呼叫setFrameDelay(longframeDelay)設定動畫幀之間的見習時間,調整幀率,減少動畫過程中頻繁繪製介面,而在不影響動畫效果的前提下減少CPU的資源消耗。最重要的是,屬性動畫是通過呼叫get、set方法來真實的控制各View的屬性值,基本可以實現所有的動畫效果。所以View必須要提供setXxx方法,如果動畫的時候沒有傳遞初始值,那麼還要提供getXxx方法,因為系統要去拿xxx屬性的初始值(如果這條不滿足,程式直接Crash) 。View的setXxx對屬性xxx所做的改變必須能夠通過某種方法反映出來,比如會帶來ui的改變啥的(如果這條不滿足,動畫無效果但不會Crash)。
舉一個最簡單的例子:
這裡寫圖片描述

    ObjectAnimator animator = ObjectAnimator.ofFloat(btn1, "translationX", 0, 500); 
    animator.setDuration(3000);
    animator.start();

  ObjectAnimator.ofFloat(btn1, “translationX”, 0, 500); 這裡第一個引數是要操縱的view,我的是一個button,第二個引數是要操縱的屬性,最後一個引數是一個可變陣列引數,傳入屬性變化的取值過程。和檢視動畫一樣可以設定動畫時長等屬性。

常見的屬性值:translationX、translationY:view物件從他佈局容器的左上角座標偏移的位置
       rotation、rotationX、rotationY:控制view圍繞支點進行2D、3D的旋轉
       scaleX、scaleY:控制view物件圍繞支點進行2D縮放
       pivotX、pivotY:view物件的支點位置,圍繞這個支點旋轉縮放,預設為view物件的中心店
       x、y:view在容器中的位置
       alpha:view的透明度
       
  ObjectAnimator.ofFloat使用時要注意屬性的資料型別,比如translationX屬性使用了ObjectAnimator.ofInt(….)方法時,就會被認為報Method setTranslationX() with type int not found on target class

錯誤;同樣一個屬性沒有對應get、set方法時,屬性動畫是不是就沒辦法了呢?答案肯定是否定的。可以通過一個自定義屬性類或者包裝類來間接的給這個屬性增加get、set方法。
例如:

private static class ViewWrapper {
        private View mTarget;

        public ViewWrapper(View target) {
            mTarget = target;
        }

        public int getWidth() {
            return mTarget.getLayoutParams().width;
        }

        public
void setWidth(int width) { mTarget.getLayoutParams().width = width; mTarget.requestLayout(); } }

這樣就給屬性包裝了一層,使用時只要操縱包裝類即可:

        ViewWrapper wrapper = new ViewWrapper(mButton);
        ObjectAnimator.ofInt(wrapper, width, 500).setDuration(5000).start();

這裡寫圖片描述

PropertyValuesHolder

  在檢視動畫中用AnimationSet可以實現多個動畫一起執行,在屬性動畫中,針對一個物件的多個屬性進行操控,完成類似AnimationSet的效果可以通過PropertyValuesHolder來實現。
例如:

        PropertyValuesHolder pvh1 = PropertyValuesHolder.ofFloat("scaleX", 1f, 0, 1f); 
        PropertyValuesHolder pvh2 = PropertyValuesHolder.ofFloat("scaleY", 1f, 0, 1f);
        PropertyValuesHolder pvh3 = PropertyValuesHolder.ofFloat("translationX",0, 500);
        ObjectAnimator.ofPropertyValuesHolder(view,pvh1,pvh2,pvh3).setDuration(3000).start();

這裡寫圖片描述

ValueAnimator

   ValueAnimator在屬性動畫中佔非常重要的地位。他本身不提供任何動畫效果,它更像一個數值發生器,用來產生一定規律的數字,從而讓調動著來控制動畫的實踐過程。ValueAnimator的一般使用方法如下所示,通常情況下,在ValueAnimator的AnimatorUpdateListenerListener中監聽數值的變化,從而完成動畫的變換。

        ValueAnimator animator = ValueAnimator.ofFloat(0,100);
        animator.setTarget(view);
        animator.setDuration(1000).start();
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                Float value = (Float)animation.getAnimatedValue();
                //use the value
            }
        });

動畫的監聽

一個完整的動畫有Start、Repat、End、Cancel四個過程,通過Android提供了介面,可以很方便的監聽這四個事件:

 animator.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) {
            }
        });

   大部分時候只關心onAnimationEnd事件,所以Android也提供了一個animatorListenerAdapter來讓我們選擇必要時間進行監聽:

animator.addListener(new AnimatorListenerAdapter() {
    @Override
    public void onAnimationEnd(Animator animation) {
    }
});

AnimatorSet

   對於一個屬性同時作用多個屬性動畫效果,可以用PropertyValuesHolder實現,但是用AnimatorSet不僅能實現這樣的效果還可以更加精確的順序控制。

        ObjectAnimator animator1 = ObjectAnimator.ofFloat(view, "translationX",500f); 
        ObjectAnimator animator2 = ObjectAnimator.ofFloat(view, "scaleX",1f,0f,1f);
        ObjectAnimator animator3 = ObjectAnimator.ofFloat(view, "scaleY",1f,0f,1f);
        AnimatorSetset = new AnimatorSet();
        set.setDuration(2000);
        set.playSequentially(animator1,animator2,animator3);
        set.start();

這裡寫圖片描述

  在屬性動畫中AnimatorSet正是通過playTogether()、playSequentially()、animSet.play().with()、before()、after()這些方法來控制多個動畫協同工作,從而做到對動畫播放順序的精確控制。