動畫效果Animation-android

desaco發表於2016-02-29

》自Android 3.0版本開始,系統給我們提供了一種全新的動畫模式,屬性動畫(property animation)。

  Android之前的補間動畫機制其實還算是比較健全的,在android.view.animation包下面有好多的類可以供我們操作,來完成一系列的動畫效果,比如說對View進行移動、縮放、旋轉和淡入淡出,並且我們還可以藉助AnimationSet來將這些動畫效果組合起來使用,除此之外還可以通過配置Interpolator來控制動畫的播放速度等。

  新引入的屬性動畫機制已經不再是針對於View來設計的了,也不限定於只能實現移動、縮放、旋轉和淡入淡出這幾種動畫操作,同時也不再只是一種視覺上的動畫效果了。它實際上是一種不斷地對值進行操作的機制,並將值賦值到指定物件的指定屬性上,可以是任意物件的任意屬性。所以我們仍然可以將一個View進行移動或者縮放,但同時也可以對自定義View中的Point物件進行動畫操作了。我們只需要告訴系統動畫的執行時長,需要執行哪種型別的動畫,以及動畫的初始值和結束值,剩下的工作就可以全部交給系統去完成了。

既然屬性動畫的實現機制是通過對目標物件進行賦值並修改其屬性來實現的,那麼之前所說的按鈕顯示的問題也就不復存在了,如果我們通過屬性動畫來移動一個按鈕,那麼這個按鈕就是真正的移動了,而不再是僅僅在另外一個位置繪製了而已。

》ValueAnimator、ObjectAnimator、AnimatorSet、組合動畫、XML配置動畫屬性

 1.屬性動畫要求動畫作用的物件提供該屬性的get和set方法,屬性動畫根據你傳遞的該熟悉的初始值和最終值,以動畫的效果多次去呼叫set方法,每次傳遞給set方法的值都不一樣,確切來說是隨著時間的推移,所傳遞的值越來越接近最終值

privatevoidperformAnimate() {
    ViewWrapper wrapper = newViewWrapper(mButton);
    ObjectAnimator.ofInt(wrapper, width, 500).setDuration(5000).start();
}
 
@Override
publicvoidonClick(View v) {
    if(v == mButton) {
        performAnimate();
    }
}
 
privatestaticclass ViewWrapper {
    privateView mTarget;
 
    publicViewWrapper(View target) {
        mTarget = target;
    }
 
    publicintgetWidth() {
        returnmTarget.getLayoutParams().width;
    }
 
    publicvoidsetWidth(intwidth) {
        mTarget.getLayoutParams().width = width;
        mTarget.requestLayout();
    }
}

> 1.View動畫(漸變動畫)的功能是有限的,大家可以嘗試使用屬性動畫

2.為了在各種安卓版本上使用屬性動畫,你需要採用nineoldandroids,它是GitHub開源專案,jar包和原始碼都可以在網上下到,如果下不到jar包,我可以發給大家

3.再複雜的動畫都是簡單動畫的合理組合,再加上本文介紹的方法,可以對任何屬性作用動畫效果,也就是說你幾乎可以做出任何動畫

4.屬性動畫中的插值器(Interpolator)和估值器(TypeEvaluator)很重要,它是實現非勻速動畫的重要手段,你應該試著搞懂它,最好你還能夠自定義它們

privatevoidperformAnimate(finalView target, finalintstart, finalintend) {
    ValueAnimator valueAnimator = ValueAnimator.ofInt(1,100);
 
    valueAnimator.addUpdateListener(newAnimatorUpdateListener() {
 
        //持有一個IntEvaluator物件,方便下面估值的時候使用
        privateIntEvaluator mEvaluator = newIntEvaluator();
 
        @Override
        publicvoidonAnimationUpdate(ValueAnimator animator) {
            //獲得當前動畫的進度值,整型,1-100之間
            intcurrentValue = (Integer)animator.getAnimatedValue();
            Log.d(TAG, current value:  + currentValue);
 
            //計算當前進度佔整個動畫過程的比例,浮點型,0-1之間
            floatfraction = currentValue / 100f;
 
            //這裡我偷懶了,不過有現成的幹嗎不用呢
            //直接呼叫整型估值器通過比例計算出寬度,然後再設給Button
            target.getLayoutParams().width = mEvaluator.evaluate(fraction, start, end);
            target.requestLayout();
        }
    });
 
    valueAnimator.setDuration(5000).start();
}
 
@Override
publicvoidonClick(View v) {
    if(v == mButton) {
        performAnimate(mButton, mButton.getWidth(), 500);
    }
}
我們可以通過Animator系列的API來控制動畫的開始、停止和取消。在 KitKat也就是API level 19中,我們還可以控制動畫的暫停和恢復。

Animator.start()  // start the animation from the beginning
Animator.end()    // end the animation
Animator.cancel() // cancel the animation
Animator.pause()  // added in API 19; pause the animation
Animator.resume() // added in API 19; resume a paused animation
你可以用end方法抑或cancel方法來停止一個播放著的動畫。在兩種方式中動畫都會終止並且只有再次呼叫start方法才會重新開始播放。兩者的區別則在於停止後動畫所在的狀態,當你使用cancel方法來停止動畫後,動畫只是停止了它的時間軸,動畫的狀態會停在一箇中間態(intermediate state)。如果通過end 方法來停止一個動畫,那麼動畫會直接快進到該動畫最後一幀並且停止,所有的物件都會保持在動畫最終結束後的狀態。即cancel讓圖片保持在停止時的中間態,但是end則讓動畫到了最後的狀態。

 >有些時候,我們需要去查詢當前動畫的狀態,這個需求可以通過下面這些方法來完成。

1
2
3
booleanisStarted() // added in API 14
booleanisRunning()
booleanisPaused()  // added in API 19

  如果當前動畫已經呼叫了start函式並且還沒播放完成也沒有被取消掉,那麼isStarted方法會返回true。請注意,isStarted 方法最低的 API 需求是 14.同時,就算是在動畫播放延遲中,該方法依然會返回 true。這就是這個方法和 isRunning 方法的不同點,isRunning 方法只會在動畫確實在播放並且還沒停止的時候返回 true。

  在 API 19 的時候,isPaused 方法被加入進來。這是由於那時候動畫可以被暫停和恢復了,如果 isPaused 返回了 true,那麼說明當前動畫是在暫停狀態下,反之亦然。

  當我們通過pause呼叫去暫停動畫時,isPaused會返回true。然後通過 resume呼叫去恢復動畫播放後,isPaused也會變成false。可以注意到,圖中如果動畫是自然結束的,動畫的狀態並沒有改變。當然,動畫停止播放後,isStarted和isRunning肯定應該是返回false的。實際上,在動畫自然停止後,如果我們再去呼叫 isStarted和isRunning他們的的確確會返回false。

相關文章