屬性動畫

Android 3.0之後引入了屬性動畫,屬性動畫能夠垂手可得的實現許多View動畫作不到的事,java

屬性動畫實現原理就是修改控件的屬性值實現的動畫。android

具體先看下類關係:性能優化


Android屬性動畫(注意最低兼容版本,不過可使用開源項目來替代低版本問題)提供瞭如下屬性:dom

  • Duration:動畫的持續時間;
  • TimeInterpolation:定義動畫變化速率的接口,全部插值器都必須實現此接口,如線性、非線性插值器;
  • TypeEvaluator:用於定義屬性值計算方式的接口,有int、float、color類型,根據屬性的起始、結束值和插值一塊兒計算出當前時間的屬性值;
  • Animation sets:動畫集合,便可以同時對一個對象應用多個動畫,這些動畫能夠同時播放也能夠對不一樣動畫設置不一樣的延遲;
  • Frame refreash delay:多少時間刷新一次,即每隔多少時間計算一次屬性值,默認爲10ms,最終刷新時間還受系統進程調度與硬件的影響;
  • Repeat Country and behavoir:重複次數與方式,如播放3次、5次、無限循環,可讓此動畫一直重複,或播放完時向反向播放;

 

XML方式屬性動畫代碼示例ide

在xml中可直接用的屬性動畫節點有ValueAnimator、ObjectAnimator、AnimatorSet。以下是官方的一個例子和解釋函數

 
  
<set
  android:ordering=["together" | "sequentially"]>

    <objectAnimator
        android:propertyName="string"
        android:duration="int"
        android:valueFrom="float | int | color"
        android:valueTo="float | int | color"
        android:startOffset="int"
        android:repeatCount="int"
        android:repeatMode=["repeat" | "reverse"]
        android:valueType=["intType" | "floatType"]/>

    <animator
        android:duration="int"
        android:valueFrom="float | int | color"
        android:valueTo="float | int | color"
        android:startOffset="int"
        android:repeatCount="int"
        android:repeatMode=["repeat" | "reverse"]
        android:valueType=["intType" | "floatType"]/>

    <set>
        ...
    </set>
</set>

 


<set>屬性佈局

<objectAnimator>屬性post

ValueAnimator同上<objectAnimator>屬性性能

XML屬性動畫使用方法優化

AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(myContext,R.animtor.property_animator);
set.setTarget(myObject);set.start();

 Java方式屬性動畫

一、ObjectAnimator:繼承自ValueAnimator,容許你指定要進行動畫的對象以及該對象的一個屬性。該類會根據計算獲得的新值自動更新屬性。大多數的狀況使用ObjectAnimator就足夠了,由於它使得目標對象動畫值的處理過程變得足夠簡單,不用像ValueAnimator那樣本身寫動畫更新的邏輯,可是ObjectAnimator有必定的限制,好比它須要目標對象的屬性提供指定的處理方法(譬如提供getXXX,setXXX方法),這時候你就須要根據本身的需求在ObjectAnimator和ValueAnimator中看哪一種實現更方便了。

ObjectAnimator類提供了ofInt、ofFloat、ofObject這個三個經常使用的方法,這些方法都是設置動畫做用的元素、屬性、開始、結束等任意屬性值。當屬性值(上面方法的參數)只設置一個時就把經過getXXX反射獲取的值做爲起點,設置的值做爲終點;若是設置兩個(參數),那麼一個是開始、另外一個是結束。

特別注意:ObjectAnimator的動畫原理是不停的調用setXXX方法更新屬性值,全部使用ObjectAnimator更新屬性時的前提是Object必須聲明有getXXX和setXXX方法。咱們一般使用ObjectAnimator設置View已知的屬性來生成動畫,而通常View已知屬性變化時都會主動觸發重繪圖操做,因此動畫會自動實現;可是也有特殊狀況,譬如做用Object不是View,或者做用的屬性沒有觸發重繪,或者咱們在重繪時須要作本身的操做,那均可以經過以下方法手動設置:

   ObjectAnimator mObjectAnimator= ObjectAnimator.ofInt(view, "customerDefineAnyThingName", 0,  1) .setDuration(2000);
       mObjectAnimator.addUpdateListener(new AnimatorUpdateListener()
        {
            @Override
            public void onAnimationUpdate(ValueAnimator animation)
            {
                //int value = animation.getAnimatedValue();  能夠獲取當前屬性值
                //view.postInvalidate();  能夠主動刷新
                //view.setXXX(value);
                //view.setXXX(value);
                //......能夠批量修改屬性
            }
        });

 在項目中的Y軸3D旋轉動畫實現實例:

ObjectAnimator.ofFloat(view, "rotationY", 0.0f, 360.0f).setDuration(1000).start();

二、PropertyValuesHolder:多屬性動畫同時工做管理類。有時候咱們須要同時修改多個屬性,那就能夠用到此類,具體以下:

PropertyValuesHolder a1 = PropertyValuesHolder.ofFloat("alpha", 0f, 1f); 
PropertyValuesHolder a2 = PropertyValuesHolder.ofFloat("translationY", 0, viewWidth); 
......
ObjectAnimator.ofPropertyValuesHolder(view, a1, a2, ......).setDuration(1000).start();

如上代碼就能夠實現同時修改多個屬性的動畫啦。

三、ValueAnimator:屬性動畫中的時間驅動,管理着動畫時間的開始、結束屬性值,相應時間屬性值計算方法等。包含全部計算動畫值的核心函數以及每個動畫時間節點上的信息、一個動畫是否重複、是否監聽更新事件等,而且還能夠設置自定義的計算類型。

特別注意:ValueAnimator只是動畫計算管理驅動,設置了做用目標,但沒有設置屬性,須要經過updateListener裏設置屬性纔會生效。

ValueAnimator animator = ValueAnimator.ofFloat(0, mContentHeight);  //定義動畫
animator.setTarget(view);   //設置做用目標
animator.setDuration(5000).start();
animator.addUpdateListener(new AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator animation){
        float value = (float) animation.getAnimatedValue();
        view.setXXX(value);  //必須經過這裏設置屬性值纔有效
        view.mXXX = value;  //不須要setXXX屬性方法
    }
});

看上去能夠發現和ObjectAnimator沒啥區別,實際上正是因爲ValueAnimator不直接操做屬性值,因此要操做對象的屬性能夠不須要setXXX與getXXX方法,你徹底能夠經過當前動畫的計算去修改任何屬性。

四、AnimationSet:動畫集合,提供把多個動畫組合成一個組合的機制,並可設置動畫的時序關係,如同時播放、順序播放或延遲播放。具體使用方法比較簡單,以下:

ObjectAnimator a1 = ObjectAnimator.ofFloat(view, "alpha", 1.0f, 0f); 
ObjectAnimator a2 = ObjectAnimator.ofFloat(view, "translationY", 0f, viewWidth); 
......
AnimatorSet animSet = new AnimatorSet(); 
animSet.setDuration(5000); 
animSet.setInterpolator(new LinearInterpolator());  
//animSet.playTogether(a1, a2, ...); //兩個動畫同時執行 
animSet.play(a1).after(a2); //前後執行
......//其餘組合方式
animSet.start();

五、Evaluators相關類解釋: Evaluators就是屬性動畫系統如何去計算一個屬性值。它們經過Animator提供的

動畫的起始和結束值去計算一個動畫的屬性值。

•  IntEvaluator:   整數屬性值。

•  FloatEvaluator: 浮點數屬性值。

•  ArgbEvaluator:  十六進制color屬性值。

•  TypeEvaluator:  用戶自定義屬性值接口,譬如對象屬性值類型不是int、float、color類型,

                       你必須實現這個接口去定義本身的數據類型

如須要實現一個自定義屬性類型和計算規則的屬性動畫,以下類型float[]:

ValueAnimator valueAnimator = new ValueAnimator();
valueAnimator.setDuration(5000);
valueAnimator.setObjectValues(new float[2]); //設置屬性值類型
valueAnimator.setInterpolator(new LinearInterpolator());
valueAnimator.setEvaluator(new TypeEvaluator<float[]>()
{
    @Override
    public float[] evaluate(float fraction, float[] startValue,float[] endValue)
    {
        //實現自定義規則計算的float[]類型的屬性值
        float[] temp = new float[2];
        temp[0] = fraction * 2;
        temp[1] = (float)Math.random() * 10 * fraction;
        return temp;
    }
});
valueAnimator.start();
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener()
{
    @Override
    public void onAnimationUpdate(ValueAnimator animation)
    {
        float[] xyPos = (float[]) animation.getAnimatedValue();
        view.setHeight(xyPos[0]);   //經過屬性值設置View屬性動畫
        view.setWidth(xyPos[1]);    //經過屬性值設置View屬性動畫
    }
});

 

六、Interpolators相關類解釋

•  AccelerateDecelerateInterolator:先加速後減速。

•  AccelerateInterpolator:加速。

•  DecelerateInterpolator:減速。

•  AnticipateInterpolator:先向相反方向改變一段再加速播放。

•  AnticipateOvershootInterpolator:先向相反方向改變,再加速播放,會超出目標值而後緩慢移動至目標值,相似於彈簧回彈。

•  BounceInterpolator:快到目標值時值會跳躍。

•  CycleIinterpolator:動畫循環必定次數,值的改變爲一正弦函數:Math.sin(2 * mCycles * Math.PI * input)。

•  LinearInterpolator:線性均勻改變。

•  OvershottInterpolator:最後超出目標值而後緩慢改變到目標值。

•  TimeInterpolator:一個容許自定義Interpolator的接口,以上都實現了該接口。

以下就是加速插值器的實現代碼,咱們自定義時也能夠相似實現:

  

 //開始很慢而後不斷加速的插值器。
    public class AccelerateInterpolator implements Interpolator {
    private final float mFactor;
    private final double mDoubleFactor;
    public AccelerateInterpolator() {
        mFactor = 1.0f;
        mDoubleFactor = 2.0;
    }
    ......
    //input  0到1.0。表示動畫當前點的值,0表示開頭,1表示結尾。
    //return  插值。值能夠大於1超出目標值,也能夠小於0突破低值。
    @Override
    public float getInterpolation(float input) {
        //實現核心代碼塊
        if (mFactor == 1.0f) {
            return input * input;
        } else {
            return (float)Math.pow(input, mDoubleFactor);
        }
    }
}

綜上能夠發現,咱們可使用現有系統提供標準的東東實現屬性動畫,也能夠經過自定義繼承相關接口實現本身的動畫,只要實現上面提到的那些主要方法便可。


Java屬性動畫拓展之ViewPropertyAnimator動畫

在Android API 12時,View中添加了animate方法,具體以下:

p

ublic class View implements Drawable.Callback, KeyEvent.Callback,AccessibilityEventSource {
     ......
     /**
     * This method returns a ViewPropertyAnimator object, which can be used to animate
     * specific properties on this View.
     *
     * @return ViewPropertyAnimator The ViewPropertyAnimator associated with this View.
     */
    public ViewPropertyAnimator animate() {
        if (mAnimator == null) {
            mAnimator = new ViewPropertyAnimator(this);
        }
        return mAnimator;
    }
    ......
}

能夠看見經過View的animate()方法能夠獲得一個ViewPropertyAnimator的屬性動畫(有人說他沒有繼承Animator類,是的,他是成員關係,不是以前那種繼承關係)。

ViewPropertyAnimator提供了一種很是方便的方法爲View的部分屬性設置動畫(切記,是部分屬性),它能夠直接使用一個Animator對象設置多個屬性的動畫;在多屬性設置動畫時,它比 上面的ObjectAnimator更加牛逼、高效,由於他會管理多個屬性的invalidate方法統一調運觸發,而不像上面分別調用,因此還會有一些性能優化。

以下就是一個例子:

myView.animate().x(0f).y(100f).start();

Java屬性動畫拓展之LayoutAnimator容器佈局動畫

Property動畫系統還提供了對ViewGroup中View添加時的動畫功能,咱們能夠用LayoutTransition對ViewGroup中的View進行動畫設置顯示。LayoutTransition的動畫效果都是設置給ViewGroup,而後當被設置動畫的ViewGroup中添加刪除View時體現出來。該類用於當前佈局容器中有View添加、刪除、隱藏、顯示等時候定義佈局容器自身的動畫和View的動畫,也就是說當在一個LinerLayout中隱藏一個View的時候,咱們能夠自定義 整個因爲LinerLayout隱藏View而改變的動畫,同時還能夠自定義被隱藏的View本身消失時候的動畫等。

咱們能夠發現LayoutTransition類中主要有五種容器轉換動畫類型,具體以下:

•  LayoutTransition.APPEARING:       當View出現或者添加的時候View出現的動畫。

•  LayoutTransition.CHANGE_APPEARING:當添加View致使佈局容器改變的時候整個佈局容器的動畫。

•  LayoutTransition.DISAPPEARING:    當View消失或者隱藏的時候View消失的動畫。

•  LayoutTransition.CHANGE_DISAPPEARING:當刪除或者隱藏View致使佈局容器改變的時候整個佈局容器的動畫。

•  LayoutTransition.CHANGE:當不是因爲View出現或消失形成對其餘View位置形成改變的時候整個佈局容器的動畫

XML方式使用系統提供的默認LayoutTransition動畫:

咱們能夠經過以下方式使用系統提供的默認ViewGroup的LayoutTransition動畫:

 

android:animateLayoutChanges=」true」

 

在ViewGroup添加如上xml屬性默認是沒有任何動畫效果的,由於前面說了,該動畫針對於ViewGroup內部東東發生改變時纔有效,

因此當咱們設置如上屬性而後調運ViewGroup的addView、removeView方法時就能看見系統默認的動畫效果了。

還有一種就是經過以下方式設置:

android:layoutAnimation=」@anim/customer_anim」

經過這種方式就能實現不少吊炸天的動畫。


Java方式使用系統提供的默認LayoutTransition動畫

在使用LayoutTransition時,你能夠自定義這幾種事件類型的動畫,也可使用默認的動畫,總之最終都是經過setLayoutTransition(LayoutTransition lt)方法把這些動畫以一個LayoutTransition對象設置給一個ViewGroup。

譬如實現如上Xml方式的默認系統LayoutTransition動畫以下:

mTransitioner = new LayoutTransition();
mViewGroup.setLayoutTransition(mTransitioner);

稍微再高端一點吧,咱們來自定義這幾類事件的動畫,分別實現他們,那麼你能夠像下面這麼處理:

mTransitioner = new LayoutTransition();
......
ObjectAnimator anim = ObjectAnimator.ofFloat(this, "scaleX", 0, 1);
......//設置更多動畫
mTransition.setAnimator(LayoutTransition.APPEARING, anim);
......//設置更多類型的動畫             
mViewGroup.setLayoutTransition(mTransitioner);

經過LayoutTransition就能實現相似小米手機計算器切換普通型和科學型的炫酷動畫了。

相關文章
相關標籤/搜索