屬性動畫總結(Property Animation)


 

一、概述

  屬性動畫可以作用在View的屬性上,對屬性進行修改,而且不要求對應的屬性一定是有顯示效果的。

 

二、屬性動畫的實現方式

  1、基礎的類Animator

  Animator是一個抽象類,是屬性動畫的基礎類。不直接使用該類。

 

  2、ObjectAnimator,繼承自ValueAnimator

  使用起來比較方便的是ObjectAnimator,可以使用ObjectAnimator直接指定需要修改的view,要修改的屬性,值的變化范圍。  

  ObjectAnimator.ofFloat(view, "rotationX", 0.0F, 360.0F)
         .setDuration(500)
         .start();  

  通過上面的代碼,就可以讓View動起來,十分方便。ObjectAnimator不止有ofFloat方法,還有ofInt,ofArgb等方法,都可以比較方便的綁定View和對應的屬性。

 

  3、ValueAnimator,繼承自Animator

  是ObjectAnimator的父類。它不能綁定到具體的屬性上,而且沒有重寫setTarget方法,而Animator中的setTarget方法為空。所以ValueAnimator實際上沒有設置View和對應的屬性。這就要求使用者自己獲取變化的值,並將值賦給具體View對象的屬性。

  當然,ValueAnimator其實也十分方便,只需要加上監控事件,在監控的事件中處理相關賦值就可以了。

     ValueAnimator animator = ValueAnimator.ofFloat(0, mScreenHeight  
                - mBlueBall.getHeight());  
        animator.setDuration(1000).start();  
        animator.addUpdateListener(new AnimatorUpdateListener()  
        {  
            @Override  
            public void onAnimationUpdate(ValueAnimator animation)  
            {  
                mBlueBall.setTranslationY((Float) animation.getAnimatedValue());  
            }  
        }); 

  可以為ValueAnimator設置重復的次數(setRepeatCount)和重復的模式(setRepeatMode),重復的模式可以是(RESTART)或者(REVERSE)。

 

  4、AnimatorSet,繼承自Animator

  如果想要在View上實現多個動畫效果,可以借助於AnimatorSet。如果多個動畫同時執行,可以使用AnimatorSet.playTogether方法;如果多個動畫按順序執行,可以使用AnimatorSet.playSequentially方法;如果多個動畫沒有統一的執行順序,AnimatorSet提供了play,with,before,after來設置多個動畫執行的順序。

  

  5、PropertyValuesHolder

  PropertyValuesHolder是屬性(Property)和值(Value)的對應。ValueAnimator和ObjectAnimator對應的ofInt、ofFloat等都是借助於PropertyValuesHolder來實現的。

  對於在View上實現多個動畫效果的要求,也可以使用PropertyValuesHolder來實現。ValueAnimator和ObjectAnimator都提供了方法,可以傳入多個PropertyValuesHolder對象,來實現在多個屬性上同時產生動畫效果的要求。  

     PropertyValuesHolder pvhX = PropertyValuesHolder.ofFloat("alpha", 1f, 0f, 1f);
        PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat("scaleX", 1f, 0, 1f);
        PropertyValuesHolder pvhZ = PropertyValuesHolder.ofFloat("rotationX", 0f, 180, 360f);
        ObjectAnimator.ofPropertyValuesHolder(iv_src, pvhX, pvhY, pvhZ).setDuration(2000).start();  

 

  6、xml

  也可以使用xml文件來定義屬性函數,然后在程序中使用AnimatorInflater.loadAnimator方法加載屬性動畫。xml中,可以使用<set>、<objectAnimator>。

 

三、監聽類

  1、AnimatorUpdateListener

  在ValueAnimator的時候提到了這個監聽類。它在計算的值發生改變的時候回調,只包含一個方法。是ValueAnimator中定義的內部類。

    /**
     * Implementors of this interface can add themselves as update listeners
     * to an <code>ValueAnimator</code> instance to receive callbacks on every animation
     * frame, after the current frame's values have been calculated for that
     * <code>ValueAnimator</code>.
     */
    public static interface AnimatorUpdateListener {
        /**
         * <p>Notifies the occurrence of another frame of the animation.</p>
         *
         * @param animation The animation which was repeated.
         */
        void onAnimationUpdate(ValueAnimator animation);

    }

 

  2、AnimatorListener

  在屬性動畫的開始、結束、取消、重復的時候回調,在Animator中定義的內部類。

    /**
     * <p>An animation listener receives notifications from an animation.
     * Notifications indicate animation related events, such as the end or the
     * repetition of the animation.</p>
     */
    public static interface AnimatorListener {
        /**
         * <p>Notifies the start of the animation.</p>
         *
         * @param animation The started animation.
         */
        void onAnimationStart(Animator animation);

        /**
         * <p>Notifies the end of the animation. This callback is not invoked
         * for animations with repeat count set to INFINITE.</p>
         *
         * @param animation The animation which reached its end.
         */
        void onAnimationEnd(Animator animation);

        /**
         * <p>Notifies the cancellation of the animation. This callback is not invoked
         * for animations with repeat count set to INFINITE.</p>
         *
         * @param animation The animation which was canceled.
         */
        void onAnimationCancel(Animator animation);

        /**
         * <p>Notifies the repetition of the animation.</p>
         *
         * @param animation The animation which was repeated.
         */
        void onAnimationRepeat(Animator animation);
    }

 

  3、AnimatorPauseListener

  在屬性動畫暫停、繼續執行的時候回調,在Animator類中定義的內部類。

    /**
     * A pause listener receives notifications from an animation when the
     * animation is {@link #pause() paused} or {@link #resume() resumed}.
     *
     * @see #addPauseListener(AnimatorPauseListener)
     */
    public static interface AnimatorPauseListener {
        /**
         * <p>Notifies that the animation was paused.</p>
         *
         * @param animation The animaton being paused.
         * @see #pause()
         */
        void onAnimationPause(Animator animation);

        /**
         * <p>Notifies that the animation was resumed, after being
         * previously paused.</p>
         *
         * @param animation The animation being resumed.
         * @see #resume()
         */
        void onAnimationResume(Animator animation);
    }

 

  AnimatorListener和AnimatorPauseListener有一個共同的實現類——AnimatorListenerAdapter 。這個類實現了兩個接口的所有方法,但是它是一個抽象類,它實現的方法都是空方法,所以沒有任何意義。只是如果我們想繼承AnimatorListener或者AnimatorPauseListener,但是不想實現所有方法時,使用AnimatorListenerAdapter會很方便。

 

四、屬性動畫的其他功能

  1、Interpolator

  Interpolator表示變化率。它可以把輸入的勻速的變化轉換成加速、減速等不同的變化率。Android提供了以下Interpolator的實現類:    

  •   AccelerateDecelerateInterpolator 在動畫開始與結束的地方速率改變比較慢,在中間的時候加速
  •   AccelerateInterpolator  在動畫開始的地方速率改變比較慢,然后開始加速
  •   AnticipateInterpolator 開始的時候向后然后向前甩
  •   AnticipateOvershootInterpolator 開始的時候向后然后向前甩一定值后返回最后的值
  •   BounceInterpolator   動畫結束的時候彈起
  •   CycleInterpolator 動畫循環播放特定的次數,速率改變沿着正弦曲線
  •   DecelerateInterpolator 在動畫開始的地方快然后慢
  •   LinearInterpolator   以常量速率改變
  •   OvershootInterpolator    向前甩一定值后再回到原來位置

  如果上面的實現類仍然不能滿足具體的場景,可以自己實現Interpolator,只需要實現float getInterpolation(float input)方法就可以了。

  Animator提供setInterpolator(TimeInterpolator)方法用於設置變化率。而實際上Interpolator接口就直接繼承了TimeInterpolator接口,並且沒有新增加任何方法或常量等信息。所以Interpolator和TimeInterpolator完全等價。

  Animation(補間動畫)及其子類,包含方法setInterpolator(Interpolator),所以Android提供的這些變化率實現類同樣適用於補間動畫。

 

  2、TypeEvaluator

  類型估值,用於計算並返回屬性值。

  TypeEvaluator的定義如下:

public interface TypeEvaluator<T> {

    public T evaluate(float fraction, T startValue, T endValue);

}

 

  3、我個人的理解是這樣,首先通過Interpolator將勻速的變化變成自己想要的變化率,然后再使用TypeEvaluator將這個變化率轉換成自己想要的數據(可能是位置對應的Point,或者其他結構的數據(比如,把位置信息和alpha值一起組裝成一個類,表示透明度和位置有明確的相關性),甚至可以是按照某種規則實現的boolean也未嘗不可,如此等等的邏輯可以在這里實現)。

  那現在有一個問題,既然Interpolator和TypeEvaluator都是計算值,為什么不把二者合在一起?個人認為可以這樣理解,這包含了一種解耦的思想。Interpolator表示速率的變化,是勻速的,是越來越快的,還是先快后慢的等等;而TypeEvaluator則用於計算View的實際狀態。兩者分開之后,不但在開始設計的時候降低了復雜度,而且可以達到更好的擴展性。如果想要調整變化率,修改Interpolator,如果想要修改View的顯示規則,則修改TypeEvaluator。  

        ValueAnimator valueAnimator = new ValueAnimator();  
        valueAnimator.setDuration(3000);  
        valueAnimator.setObjectValues(new PointF(0, 0));  
        valueAnimator.setInterpolator(new LinearInterpolator());  
        valueAnimator.setEvaluator(new TypeEvaluator<PointF>()  
        {  
            // fraction = t / duration  
            @Override  
            public PointF evaluate(float fraction, PointF startValue,  
                    PointF endValue)  
            {  
                Log.e(TAG, fraction * 3 + "");  
                // x方向200px/s ,則y方向0.5 * 10 * t  
                PointF point = new PointF();  
                point.x = 200 * fraction * 3;  
                point.y = 0.5f * 200 * (fraction * 3) * (fraction * 3);  
                return point;  
            }  
        });  
  
        valueAnimator.start();  
        valueAnimator.addUpdateListener(new AnimatorUpdateListener()  
        {  
            @Override  
            public void onAnimationUpdate(ValueAnimator animation)  
            {  
                PointF point = (PointF) animation.getAnimatedValue();  
                mBlueBall.setX(point.x);  
                mBlueBall.setY(point.y);  
  
            }  
        }); 

 

 

參考: Android 屬性動畫(Property Animation) 完全解析 (上)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM