Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android動畫學習Demo(3) 沿著貝塞爾曲線移動的Property Animation

Android動畫學習Demo(3) 沿著貝塞爾曲線移動的Property Animation

編輯:關於Android編程

Property Animation中最重要,最基礎的一個類就是ValueAnimator了。Property Animation利用ValueAnimator來跟蹤記錄對象屬性已經變化了多長時間及當前這個時間點的值。

而在ValueAnimator中,又封裝了兩個類:

1)TimeInterpolator,也稱插值器,是來計算當前動畫運動的一個跟時間有關系的比例因子。

2)TypeEvaluator,這個就是利用TimeInterpolator計算出來的因子來算出當前動畫運行到的位置。

這樣講太抽象了,我們還是先用自然語言來描述一下整個動畫的過程吧。

動畫的原理,其實就是一幀幀的畫面順著時間順序,在我們眼中形成視覺殘留的效果。所以在動畫中,時間的概念是很重要的,只有時間的變化,才能形成動畫效果。

0)動畫准備開始,我們在這裡設置了一個動畫的時長(duration),如果不設置的話,動畫的時長就是300毫秒,每個畫面顯示的時間是10ms。同時也設置了某個屬性值在這個時間段中變化的起始值start和結束值end,意思就是說,在duration時間中,屬性值要從start 變化到 end。

1)動畫開始了,過了 t 時間,ValueAnimator會根據 t / duration 算出一個時間消逝的比例因子(elapsed fraction),意思就是說,現在時間到 t了,我們假設總的時間的duration就是3t吧,那就是現在已經過了1/3時間了,那這個屬性值也應該要變化到1/3了。

2)動畫繼續,現在到了2t了,那麼現在動畫時間已經過了2/3了,那麼這個屬性值是不是已經變化到2/3了呢。

3)現在到了3t了,動畫結束了,屬性值就已經從start變成end值了。

那麼現在問題來了,如果都是這樣算的話,那動畫不就一直是很勻速的了嗎?是的,如果用的是LinearInterpolator的話。

TimeInterpolator

TimeInterpolator就是用來改變我們這個動畫速度的這樣一個類了。為什麼叫插值器呢?我理解就是,本來動畫踩著時間點,一步一步走的挺好的,它硬生生在中間的插了些值進去,或者抽了一些值出去,讓整條路變得不好走了,前面變然變上坡了,走起來就慢了,本來過去 t 時間之後,動畫的畫面也應該在1/3的位置了,但是路不好走,它就走不到1/3,而可能只走了1/4了,而後面是下坡,一激動,步伐就快了許多,又趕上去了,但是不管中間的路怎麼變化,時間點一到,一定是剛剛好落在最終的位置上的。 Android中提供的Interpolator主要有九個: 1)AccelerateDecelerateInterpolator:先加速再減速。
2)AccelerateInterpolator:一直加速。
3)AnticipateInterpolator:先往後一下,再嗖的一聲一往無前。
4)AnticipateOvershootInterpolator:先往後一下,再一直往前超過終點,再往回收一下。
5)BounceInterpolator:最後像個小球彈幾下。
6)CycleInterpolator:重復幾次,感覺就是環形進度條那種,具體我還沒試過。
7)DecelerateInterpolator:一直減速。
8)LinearInterpolator:線性,這個就是我們上面講到的很均勻的了。
9)OvershootInterpolator:到了終點之後,超過一點,再往回走。有個參數可以定義,超過的力度。
這些Interpolator都是實現了TimeInterpolator接口的類,它們只需要實現一個方法:getInterpolation (float input),將這個input根據自己的需求重新計算這個比例
第一步:當到了某時間t之後,ValueAnimator會算出某個比例 fraction = t / duration,而Interpolator會接收這個比例fraction,再調用其getInterpolation方法將這個比例因子重新計算一下,返回一個新的比例因子,比如LinearInterpolator實現的方法就是什麼都不變,如下:
public float getInterpolation(float input) {
    return input;
}
而 AccelerateDecelerateInterpolator 則會利用余弦函數的對稱性變化計算這個比例因子,如下:
public float getInterpolation(float input) {
    return (float)(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f;
}

如上所述,通過第一步 Interpolator 的插值,我們會得到一個比例因子,接下來就是要用到我們的TypeEvaluator了。

TypeEvaluator

第二步:TypeEvaluator會接受第一步中算出來的比例因子,然後算出當前的屬性的值,將其返回給ValuaAnimator,由ValueAnimator去設置對應屬性的值。 比如,我自己寫了一個BezierTypeEvaluator,根據時間的變化來讓一個按鈕沿著貝塞爾曲線移動,如下:
class BezierEvaluator implements TypeEvaluator{

		@Override
		public PointF evaluate(float fraction, PointF startValue,
				PointF endValue) {
			final float t = fraction;
			float oneMinusT = 1.0f - t;
			PointF point = new PointF();
			
			PointF point0 = (PointF)startValue;
			
			PointF point1 = new PointF();
			point1.set(width, 0);
			
			PointF point2 = new PointF();
			point2.set(0, height);
			
			PointF point3 = (PointF)endValue;
			
			point.x = oneMinusT * oneMinusT * oneMinusT * (point0.x) 
					+ 3 * oneMinusT * oneMinusT * t * (point1.x)
					+ 3 * oneMinusT * t * t * (point2.x)
					+ t * t * t * (point3.x);
			
			point.y = oneMinusT * oneMinusT * oneMinusT * (point0.y) 
					+ 3 * oneMinusT * oneMinusT * t * (point1.y)
					+ 3 * oneMinusT * t * t * (point2.y)
					+ t * t * t * (point3.y);			
			return point;
		}	
	}

自定義TypeEvaluator,我們必須實現其evaluate方法,目的就是計算出目前的對象對應屬性的值,而它會接收三個參數,一個是上文中通過interpolator算出的比例,還有我們在創建動畫時設置的起始值和結束值。

ValueAnimator.AnimatorUpdateListener

既然我們已經算出了在 t 時刻,對象的某個屬性的值,那麼我們要把這個值重新設置到對象中,才能夠起作用啊。所以ValueAnimator也提供了一個內部的Listener接口,其只有一個方法,就是獲取TypeEvaluator計算出來的值,並設置給對應的屬性,比如我們Demo中的代碼:
valueAnimator.addUpdateListener(new AnimatorUpdateListener() {			
			@Override
			public void onAnimationUpdate(ValueAnimator animation) {
				PointF pointF = (PointF)animation.getAnimatedValue();
				button.setX(pointF.x);
				button.setY(pointF.y);
			}
		});

我們在這裡改變Button的X坐標和Y坐標,從而改變其具體的位置。至於validate,然後引起重新繪制的過程,對於這些基本的屬性,ValueAnimator已經幫我們實現了。 下面,我們看看效果圖,然後再總結一下ValueAnimator的實現機制。 n峨糙铻
mv贲?'~稖?'妠^畾%j?~稖?'5?糙铻-畨噘r亘溩癘*^謦公h痬9鉌f瓂語栫坎阼?-畨噍┾櫕^uVス?奻?u玘.+-zwNx欲-畨鄋硾嶇-x?x?R梈碘獠拽z醬鐛n7湸	鈾玥畾瑗觏戎驺y薂?毝婇畩^峧g瑉荽鐛n7湸	鈾玥?黔n丁系統定義的對象的某個屬性沒有對應的get/set方法的時候,那我們怎麼辦呢? 1)最簡單的,就是去添加get/set方法,如果我們有權限的話,但很多時候我們沒有。 2)給它添加一個包裝類,引入一個get/set方法去設置本來的屬性,來間接改變其值。 3)就是利用ValueAnimator,自己去實現其變動的邏輯了。
源代碼下載
嗯,這一篇文章大概就是這樣了,大家如果有興趣了解Property Animation的應用的話,可以看一下 Android動畫學習Demo(2) 關於Property Animation的用法及總結

最後還是要提醒一下,Property Animation是3.0以後才支持的,如果大家想在3.0之前去應用這些屬性的話,可以去下載jake wharton的nineoldandroids包,基本上都可以直接將方法套上,不過據我實驗,還是有某些方法,比如 PropertyValuesHolder就會有些bug出現的。我把這個包也放在這裡吧,
點擊NineoldAndroids下載
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved