天天看點

Android 屬性動畫實作抛物線動畫

此前多次學習過安卓動畫,知道有三種動畫,知道三種動畫的特性,但是一直沒有實踐過,看了沒有多久,就忘記了,而且也不會用,這次通過實作“抛物線”動畫,對安卓的動畫有了一次較為明确的了解。

首先,安卓的三種動畫有哪三種呢?

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();
           

源碼下載下傳