Android屬性動畫(ObjectAnimator、PropertyValuesHolder、ValueAnimator、AnimatorSet)
Android屬性動畫
在Animator 框架中,使用最多的就是AnimatorSet和ObjectAnimator配合,使用ObjectAnimator進行更加精細的控制,只控制一個物件的一個屬性值,爾斯用多個ObjectAnimator組合到AnimatorSet形成一個動畫。而且ObjectAnimator能夠自動驅動,可以呼叫setFrameDelay(longframeDelay)設定動畫幀之間的見習時間,調整幀率,減少動畫過程中頻繁繪製介面,而在不影響動畫效果的前提下減少CPU的資源消耗。最重要的是,屬性動畫是通過呼叫get、set方法來真實的控制各View的屬性值,基本可以實現所有的動畫效果。所以View必須要提供setXxx方法,如果動畫的時候沒有傳遞初始值,那麼還要提供getXxx方法,因為系統要去拿xxx屬性的初始值(如果這條不滿足,程式直接Crash) 。View的setXxx對屬性xxx所做的改變必須能夠通過某種方法反映出來,比如會帶來ui的改變啥的(如果這條不滿足,動畫無效果但不會Crash)。
舉一個最簡單的例子:
ObjectAnimator animator = ObjectAnimator.ofFloat(btn1, "translationX", 0, 500);
animator.setDuration(3000);
animator.start();
ObjectAnimator.ofFloat(btn1, “translationX”, 0, 500); 這裡第一個引數是要操縱的view,我的是一個button,第二個引數是要操縱的屬性,最後一個引數是一個可變陣列引數,傳入屬性變化的取值過程。和檢視動畫一樣可以設定動畫時長等屬性。
常見的屬性值:translationX、translationY:view物件從他佈局容器的左上角座標偏移的位置
rotation、rotationX、rotationY:控制view圍繞支點進行2D、3D的旋轉
scaleX、scaleY:控制view物件圍繞支點進行2D縮放
pivotX、pivotY:view物件的支點位置,圍繞這個支點旋轉縮放,預設為view物件的中心店
x、y:view在容器中的位置
alpha:view的透明度
ObjectAnimator.ofFloat使用時要注意屬性的資料型別,比如translationX屬性使用了ObjectAnimator.ofInt(….)方法時,就會被認為報Method setTranslationX() with type int not found on target class
例如:
private static class ViewWrapper {
private View mTarget;
public ViewWrapper(View target) {
mTarget = target;
}
public int getWidth() {
return mTarget.getLayoutParams().width;
}
public void setWidth(int width) {
mTarget.getLayoutParams().width = width;
mTarget.requestLayout();
}
}
這樣就給屬性包裝了一層,使用時只要操縱包裝類即可:
ViewWrapper wrapper = new ViewWrapper(mButton);
ObjectAnimator.ofInt(wrapper, width, 500).setDuration(5000).start();
PropertyValuesHolder
在檢視動畫中用AnimationSet可以實現多個動畫一起執行,在屬性動畫中,針對一個物件的多個屬性進行操控,完成類似AnimationSet的效果可以通過PropertyValuesHolder來實現。
例如:
PropertyValuesHolder pvh1 = PropertyValuesHolder.ofFloat("scaleX", 1f, 0, 1f);
PropertyValuesHolder pvh2 = PropertyValuesHolder.ofFloat("scaleY", 1f, 0, 1f);
PropertyValuesHolder pvh3 = PropertyValuesHolder.ofFloat("translationX",0, 500);
ObjectAnimator.ofPropertyValuesHolder(view,pvh1,pvh2,pvh3).setDuration(3000).start();
ValueAnimator
ValueAnimator在屬性動畫中佔非常重要的地位。他本身不提供任何動畫效果,它更像一個數值發生器,用來產生一定規律的數字,從而讓調動著來控制動畫的實踐過程。ValueAnimator的一般使用方法如下所示,通常情況下,在ValueAnimator的AnimatorUpdateListenerListener中監聽數值的變化,從而完成動畫的變換。
ValueAnimator animator = ValueAnimator.ofFloat(0,100);
animator.setTarget(view);
animator.setDuration(1000).start();
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
Float value = (Float)animation.getAnimatedValue();
//use the value
}
});
動畫的監聽
一個完整的動畫有Start、Repat、End、Cancel四個過程,通過Android提供了介面,可以很方便的監聽這四個事件:
animator.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
});
大部分時候只關心onAnimationEnd事件,所以Android也提供了一個animatorListenerAdapter來讓我們選擇必要時間進行監聽:
animator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
}
});
AnimatorSet
對於一個屬性同時作用多個屬性動畫效果,可以用PropertyValuesHolder實現,但是用AnimatorSet不僅能實現這樣的效果還可以更加精確的順序控制。
ObjectAnimator animator1 = ObjectAnimator.ofFloat(view, "translationX",500f);
ObjectAnimator animator2 = ObjectAnimator.ofFloat(view, "scaleX",1f,0f,1f);
ObjectAnimator animator3 = ObjectAnimator.ofFloat(view, "scaleY",1f,0f,1f);
AnimatorSetset = new AnimatorSet();
set.setDuration(2000);
set.playSequentially(animator1,animator2,animator3);
set.start();
在屬性動畫中AnimatorSet正是通過playTogether()、playSequentially()、animSet.play().with()、before()、after()這些方法來控制多個動畫協同工作,從而做到對動畫播放順序的精確控制。