天天看點

和ys一起學動畫——傳統動畫與屬性動畫(二)屬性動畫

忙了幾天,又到周五了,雖然周五寫bolg好像很少人看,不過無所謂啦。主要總結和自己看看。

本文承接和ys一起學動畫——傳統動畫與屬性動畫(一) 一文繼續介紹關于屬性動畫的一些知識和自己的demo。

本來打算再往demo裡面新加一點内容的。。後來忙了一下,就沒高興寫了。。

好了,進入正題。

屬性動畫

屬性動畫(Property Animation)是一個很強勁的動畫架構,幾乎可以為所有的事物加上動畫效果。你可以定義一個動畫去改變任何對象的屬性,不管該對象是否在螢幕上,都可以進行繪制。一個屬性動畫在某一個時間段,改變的是一個對象的一個屬性值(一個對象的一個字段)。原理就是這樣。

屬性動畫相關的類

ObjectAnimator 對象動畫執行類
ValueAnimator 值動畫執行類
AnimatorSet 一組動畫的執行,有多種方式(一起執行,自定義順序執行等)
AnimtorInflater 加載xml檔案類
TypeEvaluator 類型估值,主要用于設定動畫操作屬性的值
TimeInterpolator 時間插值器
           

屬性動畫的屬性

Duration:
動畫的持續時間
TimeInterpolation: 
用于定義動畫變化率的接口,所有插值器都必須實作此接口,有線性,非線性插值器。
TypeEvaluator: 
用于定義屬性值計算方式的接口,有int,float,color類型,根據屬性的起始、結束值和插值一起計算出目前時間的屬性值,可以使用PropertyValuesHolder來捆綁多個值的變化。
Animation sets: 
動畫集合,即可以同時對一個對象應用多個動畫,這些動畫可以同時播放也可以對不同動畫設定不同的延遲
Frame refreash delay: 
多少時間重新整理一次,即每隔多少時間計算一次屬性值,預設為10ms,最終重新整理時間還受系統程序排程與硬體的影響
Repeat Country and behavoir:
重複次數與方式,如播放3次、5次、無限循環,可以讓此動畫一直重複,或播放完時向反向播放
           

對于View的屬性來說:

1)translationX 和 translationY:這兩個屬性控制了View所處的位置,
     它們的值是由layout容器設定的,是相對于坐标原點(0,0左上角)的一個偏移量。

2)rotation, rotationX 和 rotationY:控制View繞着軸點(pivotX和pivotY)旋轉。它的表現跟Tween Animation中的RotateAnimation不一緻。
RotateAnimation 的旋轉,表現為平面的旋轉
而rotationX、Y 旋轉,是立體的旋轉,預設是以View的中心點,做rotation(x,y)過中心點的直線,面向該直線進行翻轉

3)scaleX 和 scaleY:控制View基于pivotX和pivotY的縮放。

4)pivotX 和 pivotY:旋轉的軸點和縮放的基準點,預設是View的中心點。

5)x 和 y:描述了view在其父容器中的最終位置,是左上角坐标和偏移量(translationX,translationY)的和。

6)aplha:透明度,1是完全不透明,0是完全透明。
           

具體使用方法

通過調用執行類的ofFloat等方法就可以完成對動畫的初始化,支援的值類型有float,int,keyframe,object以及PropertyValuesHolder。當然,不要忘記調用setDuration和start喔。

1.ObjectAnimator

對象動畫,顧名思義,你可以為其指定一個Target對象,然後對其的某個屬性進行值的變化進而達到動畫效果。使用對象動畫有兩個條件:

①需要變化的屬性必須要有對應的set,get方法;

②指定的屬性必須是UI相關的,不然看不到效果。

//方法一 直接使用,單屬性
        ObjectAnimator//  
        .ofFloat(view, "rotationX", , )//參數:變化的View,變化的屬性,變化的值(為可變長參數)
        .setDuration()//  變化的總時長
        .start();  // 啟動動畫
           

欸對了,聽說換成妹子圖才有人氣,我得馬上試試。

和ys一起學動畫——傳統動畫與屬性動畫(二)屬性動畫
//方法二,為動畫設定監聽器,重寫onAnimationUpdate自己實作多個屬性的修改(可對相同的值進行不同處理)
        ObjectAnimator anim = ObjectAnimator//  
                .ofFloat(view, "zhy", F,  F)//  
                .setDuration();//  
        anim.start();  
        anim.addUpdateListener(new AnimatorUpdateListener()  
        {  
            @Override  
            public void onAnimationUpdate(ValueAnimator animation)  
            {  
                float cVal = (Float) animation.getAnimatedValue();  
                view.setAlpha(cVal);  
                view.setScaleX(cVal);  
                view.setScaleY(cVal);  
            }  
        });  
           
和ys一起學動畫——傳統動畫與屬性動畫(二)屬性動畫
//方法三,使用PropertyValuesHolder 捆綁多個需要改變的屬性字段(可設定不同的值)
        PropertyValuesHolder pvhX = PropertyValuesHolder.ofFloat("alpha", ,  
                , );  
        PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat("scaleX", ,  
                , );  
        PropertyValuesHolder pvhZ = PropertyValuesHolder.ofFloat("scaleY", ,  
                , );  
        ObjectAnimator.ofPropertyValuesHolder(view, pvhX, pvhY,pvhZ).setDuration().start();  
           
和ys一起學動畫——傳統動畫與屬性動畫(二)屬性動畫

2.ValueAnimator

值動畫僅僅接受值作為參數,不需要之前的屬性名,自然也沒有了必須用對象得有set、get方法的限制。但是往往需要我們自己去實作它的update邏輯。

這裡我實作了一個自由落體效果

/** 
     * 自由落體
     * @param view 
     */  
    public void verticalRun( View view)  
    {  
        ValueAnimator animator = ValueAnimator.ofFloat(f,f);  
        animator.setTarget(mBlueBall1);  
        animator.setDuration().start();
        animator.setInterpolator(new LinearInterpolator());  
        animator.addListener(new AnimatorListener() {

            @Override
            public void onAnimationStart(Animator animation) {
                // TODO Auto-generated method stub
                Log.i(TAG,"drop start");
            }

            @Override
            public void onAnimationRepeat(Animator animation) {
                // TODO Auto-generated method stub
                Log.i(TAG,"drop repeat");
            }

            @Override
            public void onAnimationEnd(Animator animation) {
                // TODO Auto-generated method stub
                Log.i(TAG,"drop end");
            }

            @Override
            public void onAnimationCancel(Animator animation) {
                // TODO Auto-generated method stub
                Log.i(TAG,"drop cancel");
            }
        });

        animator.addUpdateListener(new AnimatorUpdateListener()  
        {  
            @Override  
            public void onAnimationUpdate(ValueAnimator animation)  
            {  
                //自己實作邏輯
                float temp = (Float) animation.getAnimatedValue();
                mBlueBall1.setTranslationY((float)(mScreenHeight - mBlueBall.getHeight()) * temp * temp); 
            }  
        });

    }
           
和ys一起學動畫——傳統動畫與屬性動畫(二)屬性動畫

還有一個抛物線效果

/** 
     * 抛物線
     * @param view 
     */  
    public void paowuxian(View view)  
    {  

        ValueAnimator valueAnimator = new ValueAnimator();  
        valueAnimator.setDuration();  
        valueAnimator.setObjectValues(new PointF(, ),new PointF(mScreenWidth - mBlueBall.getWidth(),mScreenHeight - mBlueBall1.getHeight()));  
        valueAnimator.setInterpolator(new LinearInterpolator());  
        valueAnimator.setEvaluator(new TypeEvaluator<PointF>()  
        {  
            // fraction = t / duration  
            @Override  
            public PointF evaluate(float fraction, PointF startValue,  
                    PointF endValue)  
            {  
                float maxa = (float) (endValue.x - startValue.x);
                float maxb = (float) (endValue.y - startValue.y);
                PointF point = new PointF();  
                point.x = maxa * fraction;  
                point.y = maxb * (fraction * fraction); 
                return point;  
            }  
        });  

        valueAnimator.start();  
        valueAnimator.addUpdateListener(new AnimatorUpdateListener()  
        {  
            @Override  
            public void onAnimationUpdate(ValueAnimator animation)  
            {  
                PointF point = (PointF) animation.getAnimatedValue();  
                mBlueBall.setTranslationX(point.x);  
                mBlueBall.setTranslationY(point.y);  
            }  
        });  
    }  
           
和ys一起學動畫——傳統動畫與屬性動畫(二)屬性動畫

兩球同時落地(需要都使用線性時間插值器,才能達到這樣的效果):

和ys一起學動畫——傳統動畫與屬性動畫(二)屬性動畫

3.AnimatorSet

一組動畫的執行,有多種方式(一起執行,自定義順序執行等)

簡單易懂的代碼:

private void onebyone() {
        // TODO Auto-generated method stub
        float cx = mBlueBall.getX();  

        ObjectAnimator anim1 = ObjectAnimator.ofFloat(mBlueBall, "scaleX",  
                , );  
        ObjectAnimator anim2 = ObjectAnimator.ofFloat(mBlueBall, "scaleY",  
                , );  
        ObjectAnimator anim3 = ObjectAnimator.ofFloat(mBlueBall,  
                "x",  cx , );  
        ObjectAnimator anim4 = ObjectAnimator.ofFloat(mBlueBall,  
                "x", cx);  
        /** 
         * anim1,anim2,anim3,anim4依次執行
         */  
        AnimatorSet animSet = new AnimatorSet();  
        animSet.play(anim1).before(anim2);  
        animSet.play(anim2).before(anim3);  
        animSet.play(anim4).after(anim3);  
        animSet.setDuration();  
        animSet.start();  
    }

    private void together() {
        // TODO Auto-generated method stub
        ObjectAnimator anim1 = ObjectAnimator.ofFloat(mBlueBall, "scaleX",  
                ,  ,);  
        ObjectAnimator anim2 = ObjectAnimator.ofFloat(mBlueBall, "scaleY",  
                ,  ,);  
        ObjectAnimator anim3 = ObjectAnimator.ofFloat(mBlueBall, "alpha",  
                ,  ,);  
        AnimatorSet animSet = new AnimatorSet();  
        animSet.setDuration();  
        animSet.setInterpolator(new LinearInterpolator());  
        //一起執行
        animSet.playTogether(anim1, anim2,anim3);  
        animSet.start();  
    }
           

(稍後會補充一些關于LayoutAnimator的内容,插值器前面已經講了這邊我就不再贅述了)

小結

其實屬性動畫用起來沒有那麼困難,做出來效果也蠻不錯的,這裡放出demo給大家下載下傳。以後的demo都免費提供吧 。

Demo下載下傳