動畫的分類
在android3.0以前,android的動畫機制比較簡單,也可以說不健全,那時候是分為兩種實作方式:幀動畫和補間動畫。
1. 幀動畫說白了就像gif,在實作的過程中依賴一幀幀的圖檔資源,然後加載輪播
2. 補間動畫倒是可以對view做一些簡單的動态效果,但是功能過于簡陋,隻能夠實作移動、縮放、旋轉和淡入淡出這四種動畫操作,局限性很大。
在3.0之後android提供了一個更加全面和強大的動畫實作方式:屬性動畫。基于此我們可以實作各種各樣的動畫效果。當然前提你得會用….
一、屬性動畫的實作原理
屬性動畫的實作原理其實就是通過對值的不斷操作。基于這個實作機制我們就可以在view的外層或内部對view進行持續性的更改操作已完成動畫的效果。舉個栗子吧:通過以下動畫使button的透明度在3秒内從0勻速增至1
ValueAnimator valueAnimator = ValueAnimator.ofFloat(f,f);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
button.setAlpha((float)animation.getAnimatedValue());
}
});
valueAnimator.setDuration();
valueAnimator.start();
當然我們也可以通過setInterpolator()來設定值遞增的加速度。
二、ObjectAnimator
ObjectAnimator是ValueAnimator的子類,也是我們用的比較多的個動畫實作類。通過ObjectAnimator我們可以快速的實作上述效果:
ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(button, "alpha",f,f);
objectAnimator.setDuration();
objectAnimator.start();
這裡就表示在3000毫秒内對button的alpha屬性進行操作,使其值從0遞增到1,進而實作button的透明值漸變動畫。這裡”alpha”表示對button的alpha屬性進行操作,我們還可以傳入”rotation”,”translationX”,”translationY”對view的旋轉和位移進行動畫表示。
三、組合動畫
有時候單一的屬性并不足以支撐我們的動畫效果,這時候就需要使用組合動畫,組合動畫通過AnimatorSet将多個ObjectAnimator動畫組合成一個動畫集合進行展示。
// 使按鈕從左側進入
ObjectAnimator moveIn = ObjectAnimator.ofFloat(button, "translationX", -, );
moveIn.setDuration();
// 使按鈕變為透明,再還原
ObjectAnimator alphaAnimator = ObjectAnimator.ofFloat(button, "alpha",,,);
alphaAnimator.setDuration();
// 使按鈕旋轉360°
ObjectAnimator rotationAnimator = ObjectAnimator.ofFloat(button, "rotation", , );
rotationAnimator.setDuration();
// 組合上面三個動畫
AnimatorSet animators = new AnimatorSet();
animators.play(alphaAnimator).with(rotationAnimator).after(moveIn);
animators.start();
animatorSet有4個方法用以實作動畫的組合邏輯,分别是:
1. after(Animator anim) 将現有動畫插入到傳入的動畫之後執行
2. after(long delay) 将現有動畫延遲指定毫秒後執行
3. before(Animator anim) 将現有動畫插入到傳入的動畫之前執行
4. with(Animator anim) 将現有動畫和傳入的動畫同時執行
after\before\with不光可以傳入單一的屬性動畫, 也可以傳入AnimatorSet組合動畫。這樣我們就能組合出特殊效果的動畫了。
// 垂直方向縮放大小
ObjectAnimator scaleYAnimator = ObjectAnimator.ofFloat(button,"scaleY",,,);
scaleYAnimator.setDuration();
// 組合animators動畫集合和scaleYAnaimator
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.play(animatorSet).with(scaleYAnimator);
animatorSet.start();
四、動畫監聽
我們還可以監聽動畫在不同的節點的事件并執行相應的處理,比如開始動畫、結束動畫。Animator總共提供了4個監聽事件如下:
animatorSet.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) {
}
});
ObjectAnimator和AnimatorSet都是繼承自Animator,是以他們都有AnimatorListener監聽接口。很多時候我們并不會監聽所有的事件,可能隻會單獨監聽開始事件或者結束事件,我們可在這裡傳入實作了AnimatorListener的抽象類AnimatorListAdapter,然後選擇性的實作AnimatorListener的某個或者多個事件。如下:
animator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
// do anything
}
});
五、Interpolator插值器
Interpolator主要是用來控制動畫的變化率的,打個比方說,自由落體運動,剛開始下落的速度為0,但是由于重力加速度導緻其下落速度逐漸增大。Interpolator的作用就相當于重力加速度。現有系統提供了以下幾種插值器:
1. LinearInterpolator(線性插值器):勻速動畫。
2. AccelerateDecelerateInterpolator(加速減速插值器):動畫兩頭慢,中間快。
3. DecelerateInterpolator(減速插值器):動畫越來越慢。
4. BounceInterpolator(彈跳插值器):先加速至指向位置,然後反彈數次,逐漸停留至預定目标值。
5. CycleInterpolator(周期插值器):重複動畫數次,依照正弦曲線的頻率執行。
6. OvershootInterpolator:加速執行,會超出預定目标值,最火回至預定目标值。
7. AnticipateInterpolator:先反向執行,然後加速正向執行至目标值。
8. AnticipateOvershootInterpolator:先反向執行,然後加速正向執行, 會超出預定目标值,最後回至預定目标值。
動畫未設定或者傳入插值器為空,則預設采用LinearInterpolator插值器。
六、XML編寫動畫
我們就以最後一個組合的動畫為例,采用xml進行編寫實作。
xml代碼如下:
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:ordering="sequentially" >
<!--從左側平移進入-->
<objectAnimator
android:duration="2000"
android:propertyName="translationX"
android:valueFrom="-500"
android:valueTo="0"
android:valueType="floatType" >
</objectAnimator>
<set android:ordering="together" >
<!--旋轉360度-->
<objectAnimator
android:duration="3000"
android:propertyName="rotation"
android:valueFrom="0"
android:valueTo="360"
android:valueType="floatType" >
</objectAnimator>
<set android:ordering="sequentially">
<!--變透明,再還原-->
<objectAnimator
android:duration="1500"
android:propertyName="alpha"
android:valueFrom="1"
android:valueTo="0"
android:valueType="floatType" >
</objectAnimator>
<objectAnimator
android:duration="1500"
android:propertyName="alpha"
android:valueFrom="0"
android:valueTo="1"
android:valueType="floatType" >
</objectAnimator>
</set>
</set>
<!--垂直方向放大,再還原-->
<objectAnimator
android:duration="1500"
android:propertyName="scaleY"
android:valueFrom="1"
android:valueTo="3"
android:valueType="floatType" >
</objectAnimator>
<objectAnimator
android:duration="1500"
android:propertyName="scaleY"
android:valueFrom="3"
android:valueTo="1"
android:valueType="floatType" >
</objectAnimator>
</set>
-
節點
xml檔案裡共用了兩個節點,分别是set、objectAnimator分别對應代碼裡的AnimatorSet和ObjectAnimator。那麼他們的屬性也就一目了然了。其中不一樣的是xml配置的動畫執行邏輯。
-
屬性配置
在代碼裡我們可通過with/after/before來配置其執行次序,但在xml裡的先後順序則是根據代碼的先後順序确定的,,也就是說xml裡隻有兩種順序關系,先後和同時。android:ordering=”sequentially”表示順序執行,android:ordering=”together”表示同時執行。其他屬性則可對應代碼裡設定方法。