Android的動畫形式共分為三種,View動畫,幀動畫與屬性動畫。
先對這三種動畫做一個概述:
View動畫是一種漸進式動畫,通過圖像的平移、縮放、旋轉和透明度等各種漸進式變換完成動畫效果。
幀動畫是通過不停的切換圖檔實作動畫效果。
屬性動畫是不停的改變對象的屬性來實作動畫效果。
View動畫:
Android系統提供的View動畫分為四類,RotateAnimation,ScaleAnimation,TranslateAnimation,AlphaAnimation,此外,Android還提供了AnimationSet,将四種動畫進行組合使用。View動畫可以通過setDuration方法,setInterpolator方法,setAnimationListener和setFillAfter方法來設定動畫運作的時長,動畫的播放速度,對動畫進行監聽和動畫運作結束後View的狀态。
View動畫還可以為ViewGroup和Activity設定動畫。
幀動畫:
幀動畫就是不停的切換圖檔來實作動畫效果,就如同小人書,但比較容易出現OOM,是以在使用時,需要注意圖檔大小。
屬性動畫:
View動畫的那四種效果有很明顯的缺點,繪制出來的效果其實并沒有真正改變View的屬性,即left、top、right和bottom的值,隻是系統臨時繪制的結果。這樣View的點選位置并沒有發生變化。針對這個問題,從Android3.0開始屬性動畫應運而生。
屬性動畫本質是通過改變新增的屬性(如平移translationX/Y、縮放scaleX/Y、旋轉rotationX/Y等)并重新整理螢幕來實作動畫效果,并且實作點選位置的實時改變。但是屬性動畫仍然不會修改原始的上下左右四個值。最後需要注意的是,屬性動畫不止用于View,還可以用于任何對象。
ValueAnimator是整個屬性動畫機制中最核心的一個類,屬性動畫的運作機制是通過不斷地對值進行操作來實作的,而初始值和結束值之間的動畫過渡就是由ValueAnimator類來負責計算的。它的内部使用一種時間循環的機制來計算值與值之間的動畫過渡,我們隻需要将初始值和結束值提供給ValueAnimator,并且告訴它動畫所需運作的時長,那麼ValueAnimator就會自動幫我們完成從初始值平滑地過渡到結束值這樣的效果。除此之外,ValueAnimator還負責管理動畫的播放次數、播放模式、以及對動畫設定監聽器等,确實是一個非常重要的類。
ObjectAnimator是我們最常接觸的類,它繼承自ValueAnimator。由于ValueAnimator隻是對值進行了一個平滑的動畫過渡,我們在實際中應用的場景并不多。而ObjectAnimator就不同了,它可以直接對任意對象的任意屬性進行動畫操作,例如 alpha, rotation, translationX, translationY, scaleX, scaleY等。我們同樣可以使用AnimationSet來将不同屬性的動畫進行組合。
Animator監聽器
Animator類中提供了addListener方法來對屬性動畫進行監聽,這個方法接收一個AnimationListener,我們隻需要實作AnimationListener就可以監聽動畫的各種事件了。我們已經知道了ObjectAnimator繼承自ValueAnimator,而ValueAnimator又繼承自Animator,是以,ObjectAnimator與ValueAnimator都可以使用addListener方法來對動畫進行監聽。
anim.addListener(new AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
}
@Override
public void onAnimationCancel(Animator animation) {
}
});
但有時候我們并不會使用AnimationListener中的所有方法,這就會造成出現很多空方法的狀況。這種情況下,我們可以使用AnimationListenerAdapter,裡面已經定義了每個方法的空方法,我們隻需要重寫我們需要的方法就可以了。
Animator類還可添加更新監聽器,如下,
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
Point point = (Point)animation.getAnimatedValue();
circle.x = point.getX();
circle.y = point.getY();
circle.invalidate();
}
})
在AnimatorUpdateListener接口中的onAnimationUpdate方法中,調用animation.getAnimatedValue()方法即可獲得Animator更新後的最新屬性(ObjectAnimator)或值(ValueAnimator)。
插值器TimeInterpolator與估值器TypeEvaluator
public interface TimeInterpolator {
/**
* Maps a value representing the elapsed fraction of an animation to a value that represents
* the interpolated fraction. This interpolated value is then multiplied by the change in
* value of an animation to derive the animated value at the current elapsed animation time.
*
* @param input A value between 0 and 1.0 indicating our current point
* in the animation where 0 represents the start and 1.0 represents
* the end
* @return The interpolation value. This value can be more than 1.0 for
* interpolators which overshoot their targets, or less than 0 for
* interpolators that undershoot their targets.
*/
float getInterpolation(float input);
}
public interface TypeEvaluator<T> {
/**
* This function returns the result of linearly interpolating the start and end values, with
* <code>fraction</code> representing the proportion between the start and end values. The
* calculation is a simple parametric calculation: <code>result = x0 + t * (x1 - x0)</code>,
* where <code>x0</code> is <code>startValue</code>, <code>x1</code> is <code>endValue</code>,
* and <code>t</code> is <code>fraction</code>.
*
* @param fraction The fraction from the starting to the ending values
* @param startValue The start value.
* @param endValue The end value.
* @return A linear interpolation between the start and end values, given the
* <code>fraction</code> parameter.
*/
public T evaluate(float fraction, T startValue, T endValue);
}
插值器TimeInterpolator是用來控制動畫的節奏快慢的,估值器TypeEvaluator是用來控制動畫的實作的。
TimeInterpolator接口中的getInterpolation方法接收一個float變量input,input的取值範圍為0~1,表示目前運作了的時間在設定時間中的位置,傳回值即為TypeEvaluator接口中evaluate方法中的參數fraction。evaluate方法根據傳入的fraction,起始值startValue,結束值endValue來控制動畫。ofFloat與ofInt預設使用FloatEvaluator類和IntEvaluator類。
public class FloatEvaluator implements TypeEvaluator<Number> {
/**
* This function returns the result of linearly interpolating the start and end values, with
* <code>fraction</code> representing the proportion between the start and end values. The
* calculation is a simple parametric calculation: <code>result = x0 + t * (v1 - v0)</code>,
* where <code>x0</code> is <code>startValue</code>, <code>x1</code> is <code>endValue</code>,
* and <code>t</code> is <code>fraction</code>.
*
* @param fraction The fraction from the starting to the ending values
* @param startValue The start value; should be of type <code>float</code> or
* <code>Float</code>
* @param endValue The end value; should be of type <code>float</code> or <code>Float</code>
* @return A linear interpolation between the start and end values, given the
* <code>fraction</code> parameter.
*/
public Float evaluate(float fraction, Number startValue, Number endValue) {
float startFloat = startValue.floatValue();
return startFloat + fraction * (endValue.floatValue() - startFloat);
}
}
public class IntEvaluator implements TypeEvaluator<Integer> {
/**
* This function returns the result of linearly interpolating the start and end values, with
* <code>fraction</code> representing the proportion between the start and end values. The
* calculation is a simple parametric calculation: <code>result = x0 + t * (v1 - v0)</code>,
* where <code>x0</code> is <code>startValue</code>, <code>x1</code> is <code>endValue</code>,
* and <code>t</code> is <code>fraction</code>.
*
* @param fraction The fraction from the starting to the ending values
* @param startValue The start value; should be of type <code>int</code> or
* <code>Integer</code>
* @param endValue The end value; should be of type <code>int</code> or <code>Integer</code>
* @return A linear interpolation between the start and end values, given the
* <code>fraction</code> parameter.
*/
public Integer evaluate(float fraction, Integer startValue, Integer endValue) {
int startInt = startValue;
return (int)(startInt + fraction * (endValue - startInt));
}
}
從上面FloatEvaluator和IntEvaluator的evaluator方法,我們可以很清晰的看出,隻是将簡單的計算了startValue與endValue中間的fraction處的值傳回即可。
如果是ofObject方法,則需要自己定義TypeEvaluator,隻需實作TimeInterpolator接口即可。
如果不自定義TimeInterpolator,預設getInterpolation方法預設直接傳回input。我們可以使用setInterpolator方法設定自定義的TimeInterpolator。根據input計算不同的fraction,便可控制動畫運作的速率變化。
好了,屬性動畫就是這麼簡單,你學會了嗎?