此前多次學習過安卓動畫,知道有三種動畫,知道三種動畫的特性,但是一直沒有實踐過,看了沒有多久,就忘記了,而且也不會用,這次通過實作“抛物線”動畫,對安卓的動畫有了一次較為明确的了解。
首先,安卓的三種動畫有哪三種呢?
1、Tween Animation 漸變(補間)動畫
2、Animation-list 逐幀動畫
3、Property Animation——Animator 屬性動畫
以我的了解方式來解釋這三種動畫,以操作一個view為例。
第一,補間動畫Tween Animation是四種動畫類型(位移、旋轉、透明度、伸縮)操作于這個view, 使這個view産生相應的視覺效果,但是沒有改變view本身的任何屬性(這個不想多解釋了,每篇動畫文章都會提到這句)。補間動畫對應4個動畫類:AlphaAnimation(透明度)、ScaleAnimation(縮放)、TranslateAnimation(位移)、RotateAnimation(旋轉),我們可以在代碼中,通過操作這4個類,來實作自己想要的動畫效果,當然,我們也可以使用布局檔案來實作(alph、scale、translate、rotate)。
第二,逐幀動畫Animation-list 是按照給定的順序,輪流顯示一定數目的圖像而顯示的動畫效果。參考博文http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2014/1106/1915.html
第三,屬性動畫Animator,其實跟Tween 很像,也是那4種基礎動畫方式,但是屬性動畫可以改變view本身的屬性,并且屬性動畫大體分為兩種,第一種是跟tween十分相似的,ObjectAnimator,通過ofFloat、ofInt、ofObject來實作跟tween動畫相似的動畫方式。第二種是,ValueAnimator是計算動畫過程中變化的值,包含動畫的開始值,結束值,持續時間等屬性。但并沒有把這些計算出來的值應用到具體的對象上面,是以也不會有什麼的動畫顯示出來。要把計算出來的值應用到對象上,必須為ValueAnimator注冊一個監聽器ValueAnimator.AnimatorUpdateListener,該監聽器負責更新對象的屬性值。在實作這個監聽器的時候,可以通過getAnimatedValue()的方法來擷取目前幀的值。 此時,我隻想說,動畫實在太複雜了!!這裡我先簡單介紹了3類動畫的概念,接下來介紹一下實作抛物線動畫,分别使用屬性動畫跟補間動畫實作,那些負責的動畫還沒研究透徹,以後研究透徹了再寫 !
抛物線動畫的實作
首先,套用一句别人那裡學來的話,了解一下抛物線動畫的原理:兩個位移動畫,一個橫向勻速移動,一個縱向變速移動,兩個動畫同時執行,就有了抛物線的效果。
然後,我們看一下兩個動畫相同的代碼部分
起始點、終點位置
//擷取起點坐标
int[] location2 = new int[2];
readingIV.getLocationInWindow(location2);
int x1 = location2[0];
int y1 = location2[1];
//擷取終點坐标,最近拍攝的坐标
int[] location = new int[2];
mRecentPhoto.getLocationInWindow(location);
int x2 = location[0];
int y2 = location[1]
1、補間動畫實作方式
//兩個位移動畫
TranslateAnimation translateAnimationX = new TranslateAnimation(, -(x1 - x2)-offsetX, , ); //橫向動畫
TranslateAnimation translateAnimationY = new TranslateAnimation(, , , y2 - y1 + offsetY); //豎向動畫
translateAnimationX.setInterpolator(new LinearInterpolator()); //橫向動畫設為勻速運動
translateAnimationX.setRepeatCount();// 動畫重複執行的次數
translateAnimationY.setInterpolator(new AccelerateInterpolator()); //豎向動畫設為開始結尾處加速,中間迅速
translateAnimationY.setRepeatCount();// 動畫重複執行的次數
// 組合動畫
AnimationSet anim = new AnimationSet(false);
anim.setFillAfter(false); //動畫結束不停留在最後一幀
anim.addAnimation(translateAnimationX);
anim.addAnimation(translateAnimationY);
anim.setAnimationListener(new Animation.AnimationListener() { //抛物線動畫結束後,執行淡出動畫
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationRepeat(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
AlphaAnimation alphaAnim = new AlphaAnimation(f, f);//淡出動畫
alphaAnim.setDuration();
alphaAnim.setInterpolator(new LinearInterpolator());
alphaAnim.setFillAfter(false); //動畫結束不停留在最後一幀
alphaAnim.setRepeatCount();// 動畫重複執行的次數
readingIV.clearAnimation();
readingIV.startAnimation(alphaAnim);
alphaAnim.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
readingIV.setVisibility(View.INVISIBLE);
refreshCouldIndicator(activity, null, null);
}
@Override
public void onAnimationRepeat(Animation animation) {
}
});
}
});
// 播放
readingIV.setVisibility(View.VISIBLE);
refreshCouldIndicator(activity, null, null);
anim.setDuration();// 動畫的執行時間
anim.setStartOffset();
readingIV.startAnimation(anim);
通過以上方法,可以實作抛物線,并在結束的位置執行淡出動畫。但是,在部分機型上, 發現該動畫執行結束後, 淡出動畫會跑到起始位置執行, 但是大部分機型都是沒問題的, 這種适配問題我沒搞清楚是什麼原因導緻的, 但是既然是回到初始位置執行,那麼就說明跟view的屬性沒發生變化有關,于是采用屬性動畫來實作,解決了該問題,原理幾乎相同。
//抛物線動畫
ObjectAnimator translateAnimationX = ObjectAnimator.ofFloat(view, "translationX", , -(x1 - x2) - offsetX);
translateAnimationX.setDuration();
translateAnimationX.setInterpolator(new LinearInterpolator());
// translateAnimationX.start();
ObjectAnimator translateAnimationY = ObjectAnimator.ofFloat(view, "translationY", , y2 - y1 + offsetY);
translateAnimationY.setDuration();
translateAnimationY.setInterpolator(new AccelerateInterpolator());
//縮小動畫
ObjectAnimator scaleX = ObjectAnimator.ofFloat(view, "scaleX", , );
scaleX.setDuration();
ObjectAnimator scaleY = ObjectAnimator.ofFloat(view, "scaleY", , );
scaleY.setDuration();
scaleY.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
anim_mask_layout.removeView(readingIV);
setLvTouch(activity, false);
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
});
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.play(translateAnimationX).with(translateAnimationY);
animatorSet.play(scaleX).with(scaleY).after(translateAnimationX);
animatorSet.start();
源碼下載下傳