7.ViewPropertyAnimator

ViewPropertyAnimator概述

屬性動畫已不再是針對于View而進行設計的了,而是一種對數(shù)值不斷操作的過程,我們可以將屬性動畫對數(shù)值的操作過程設置到指定對象的屬性上來,從而形成一種動畫的效果。雖然屬性動畫給我們提供了ValueAnimator類和ObjectAnimator類,在正常情況下,基本都能滿足我們對動畫操作的需求,但ValueAnimator類和ObjectAnimator類本身并不是針對View對象的而設計的,而我們在大多數(shù)情況下主要都還是對View進行動畫操作的,因此Google官方在Android 3.1系統(tǒng)中補充了ViewPropertyAnimator類,這個類便是專門為View動畫而設計的。

優(yōu)點:

  • 專門針對View對象動畫而操作的類。
  • 提供了更簡潔的鏈式調用設置多個屬性動畫,這些動畫可以同時進行的。
  • 擁有更好的性能,多個屬性動畫是一次同時變化,只執(zhí)行一次UI刷新(也就是只調用一次invalidate,而n個ObjectAnimator就會進行n次屬性變化,就有n次invalidate)。
  • 每個屬性提供兩種類型方法設置。scaleX()/scaleXBy()
  • 該類只能通過View的animate()獲取其實例對象的引用。

用法:鏈式調用,自動start,同時一次UI刷新, 簡化流程提高效率。

AnimatorSet set = new AnimatorSet();
set.playTogether( ObjectAnimator.ofFloat(btn,"alpha",0.5f),
        ObjectAnimator.ofFloat(btn,"rotation",360),
        ObjectAnimator.ofFloat(btn,"scaleX",1.5f),
        ObjectAnimator.ofFloat(btn,"scaleY",1.5f),
        ObjectAnimator.ofFloat(btn,"translationX",0,50),
        ObjectAnimator.ofFloat(btn,"translationY",0,50)
);
set.setDuration(5000).start();
//自動調用start方法
btn.animate().alpha(0.5f).rotation(360).scaleX(1.5f).scaleY(1.5f)
              .translationX(50).translationY(50).setDuration(5000);

每個屬性,兩種類型方法設置:

  • rotationX(20) 改變到某個值。 旋轉到20度。再調用一次的話,由于已經(jīng)到20度的位置,便不在有變化。
  • rotationXBy(20) 改變某個值的量。 旋轉20度。再調用一次的話,繼續(xù)旋轉20度,到40度的位置。
public ViewPropertyAnimator scaleY(float value) {
        animateProperty(SCALE_Y, value);
        return this;
    }

public ViewPropertyAnimator scaleYBy(float value) {
    animatePropertyBy(SCALE_Y, value);
    return this;
    
-----------------------------------------------------------------------------

private void animateProperty(int constantName, float toValue) {
        float fromValue = getValue(constantName);
        float deltaValue = toValue - fromValue;
        animatePropertyBy(constantName, fromValue, deltaValue);
    }

private void animatePropertyBy(int constantName, float byValue) {
        float fromValue = getValue(constantName);
        animatePropertyBy(constantName, fromValue, byValue);
    }
    
----------scale/rotation/alpha等方法,到最后都是調用該方法-----------------------------------

/**
     * Utility function, called by animateProperty() and animatePropertyBy(), which handles the
     * details of adding a pending animation and posting the request to start the animation.
     *
     * @param constantName The specifier for the property being animated
     * @param startValue The starting value of the property
     * @param byValue The amount by which the property will change
     */
    private void animatePropertyBy(int constantName, float startValue, float byValue) {
        // First, cancel any existing animations on this property
        if (mAnimatorMap.size() > 0) {
            Animator animatorToCancel = null;
            Set<Animator> animatorSet = mAnimatorMap.keySet();
            for (Animator runningAnim : animatorSet) {
                PropertyBundle bundle = mAnimatorMap.get(runningAnim);
                // 如果在該屬性上已經(jīng)有動畫,則結束該屬性上的動畫。
                if (bundle.cancel(constantName)) {
                    // property was canceled - cancel the animation if it's now empty
                    // Note that it's safe to break out here because every new animation
                    // on a property will cancel a previous animation on that property, so
                    // there can only ever be one such animation running.
                    if (bundle.mPropertyMask == NONE) {
                        // the animation is no longer changing anything - cancel it
                        animatorToCancel = runningAnim;
                        break;
                    }
                }
            }
            if (animatorToCancel != null) {
                animatorToCancel.cancel();
            }
        }

        // 封裝該屬性和值,放入集合中
        NameValuesHolder nameValuePair = new NameValuesHolder(constantName, startValue, byValue);
        mPendingAnimations.add(nameValuePair);
        mView.removeCallbacks(mAnimationStarter);
        //雖然每次操作屬性都post了該Runnable類,但是每次都把原來的移除了,始終都在維護一個最新的集合post。
        //TODO ??? post給系統(tǒng),然后系統(tǒng)按順序調用,假如系統(tǒng)很閑,post了立馬就start,那么下一個屬性設置的時候呢,怎么保證每個屬性的設置都放到集合里了才開始start?
        mView.postOnAnimation(mAnimationStarter);
    }

后續(xù)監(jiān)聽什么的,還沒研究。 資料鏈接。

原理流程:
image

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容