Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android群英傳筆記——第七章:Android動畫機制和使用技巧

Android群英傳筆記——第七章:Android動畫機制和使用技巧

編輯:關於Android編程

Android動畫效果一直是人家中十分重要的一部分,從早期的Android版本中,由於動畫機制和繪圖機制的不健全,Android的人機交互備受诟病,Android從4.X開始,特別是5.X,動畫越來越完善了,Google也開始重視這一方面了,我們本章學習的主要內容有Android視圖動畫‘ Android屬性動畫 Android動畫實例。

一.Android View動畫框架

Animation動畫框架定義了透明度,旋轉,縮放個移動等幾種動畫,而且控制了整個的View,實現原理是每次繪制視圖的時候View所在的ViewGroup中drawChild函數獲取該View的Animation的Transformation值,然後調用了canvas.concat方法,通過矩陣運算完成動畫幀,如果動畫沒有完成則繼續調用invalidate()方法啟動下回繪制來驅動動畫,從而完成整個動畫的繪制

視圖動畫使用簡單,效果豐富,它提供了AlphaAnimation,RotateAnimatio,TranslateAnimation,ScaleAnimation四種動畫方式,並提供了Animationset動畫集合,混合使用多種動畫,在Android3.0之前,視圖動畫一家獨大,但隨著Android3.0之後屬性動畫框架的推出它的風光就大不如前了。相比屬性動畫,視圖動畫的一個非常大的缺陷就是不具備交互性,當某個元件發生視圖動畫後,其響應事件的位置還依然在動畫前的地方,所以視圖動畫只能做普通的顯示效果,避免交互的發生,但是它的優點也非常明顯,即效率比較高且使用方便。視圖動畫使用非常簡單, 不僅可以通過XML文件來描述一個動畫過程,同樣也可以使用代碼來控制整個動畫過程

下面這個實例就列舉了一些簡單的視圖動畫使用方法

1.透明動畫

為視圖增加透明度的變換動畫

AlphaAnimation al = new AlphaAnimation(0,1);
al.setDuration(2000);
alpha.startAnimation(al);

2.旋轉動畫

 RotateAnimation ro = new RotateAnimation(0,300,100,100);
 ro.setDuration(2000);
 rotate.setAnimation(ro);

3.平移動畫

TranslateAnimation tr = new TranslateAnimation(0,200,0,300);
tr.setDuration(2000);
translate.setAnimation(tr);

4.縮放動畫

 ScaleAnimation sc = new ScaleAnimation(0,2,0,2);
 sc.setDuration(2000);
 scale.setAnimation(sc);

5.動畫集合

AnimationSet setAnimation = new AnimationSet(true);
setAnimation.setDuration(2000);

AlphaAnimation als = new AlphaAnimation(0,1);
als.setDuration(2000);
setAnimation.addAnimation(als);

RotateAnimation ros = new RotateAnimation(0,300,100,100);
ros.setDuration(2000);
setAnimation.addAnimation(ros);

set.startAnimation(setAnimation);

我們一起來運行一下看效果

這裡寫圖片描述

當然,有動畫,就有監聽,我們來監聽一下動畫,以透明動畫為例

AlphaAnimation al = new AlphaAnimation(0,1);
                al.setDuration(2000);
                alpha.startAnimation(al);

                al.setAnimationListener(new Animation.AnimationListener() {
                    @Override
                    public void onAnimationStart(Animation animation) {
                        Log.i("Animation","開始");
                    }

                    @Override
                    public void onAnimationEnd(Animation animation) {
                        Log.i("Animation","結束");
                        Toast.makeText(MainActivity.this,"動畫結束",Toast.LENGTH_LONG).show();
                    }

                    @Override
                    public void onAnimationRepeat(Animation animation) {

                    }
                });

執行之後打印LOG

這裡寫圖片描述

當然,我們眼見為實

這裡寫圖片描述

通過監聽,我們就可以了解動畫的動向了

二.Android屬性動畫分析

屬性動畫在Animator框架裡的,用的最多的也就是AnimatorSet和ObjectAnimator配合,使用ObjectAnimator進行更精細化的控制,只控制一個對象的屬性,而使用多個ObjectAnimator組合到AnimatorSet形成一個動畫,而且ObjectAnimator能夠自動驅動,單證各種好處,我們來看一下

1.ObjectAnimator

ObjectAnimator是屬性動畫框架中最重要的實行類,創建一個ObjectAnimator只需通過他的靜態工廠類直接返回一個ObjectAnimator對象,參數包括一個對象和對象的屬性名字,但這個屬性必須有get和對函數,內部會通過Java反射機制來調用set函數修改對象屬性值.同樣你也可以調用setIn設置相應的差值器。下面這個小例子就完成了一個非常簡單的平移動畫,

這裡寫圖片描述

在前面的講解中說到,以前的動畫框架所產生的動畫,並不能改變事件響應的位置,它只是單純地修改了顯示.如果使用舊的視圖動畫產生上面的效果,那麼按鈕的實際點擊有效區依然在原來的地方,點擊移動後的地方是不會有點擊事件發生的.而屬性動圓則不同,由於它真實地改變了一個View的屬性,所以事件響應的區域也同樣發生了改變,這時候點擊移動後的按鈕, 就會響應點擊事件了

讓我們來看看這個簡單的平移動畫是如何實現的.麻雀雖小五髒俱全,這個簡單的例子基本上就涵蓋了ObjectAnimatZ喎?/kf/ware/vc/" target="_blank" class="keylink">vcrXEy/nT0NaqyrY8L3A+DQo8L2Jsb2NrcXVvdGU+DQo8cHJlIGNsYXNzPQ=="brush:java;"> ObjectAnimator ob = ObjectAnimator.ofFloat(object,"translationX",300); ob.setDuration(2000); ob.start();

通過ObjectAnimator的靜態工廠方法,創建個ObjectAnimator對象,第一個參數自然是要操縱的view,第二個參數則是要操縱的屬性 而最後個參數是一個可變數組參數,需要傳遞進去該屬性變化的一個取值過程,

不過,在使用ObjectAnimator的時候,有一點是非常重要的,就是操縱的set,get方法,不然ObjectAnimator是無效的,下面我們具體舉一些值

translationX和 translationY:這兩個屬性作為一種增量來控制著View對象從它布局容器的左上角坐標便宜的位置。

rotation、rotationX和rotationY:這三個屬性控制View對象圍繞支點進行2D和3D旋轉

scaleX和scaleY. 這兩個屬性控制著View對象圍繞它的支點進行2D縮放。

pivotX和pivotY:這兩個屬性控制著view對象的支點位置,圍繞這個支點進行旋轉和縮放變換處理,默認情況下,該支點的位置就是View對象的中心點。

x和y這是兩個簡單實用的屬性,它描述了View對象在它的容器中的最終位置,它是最初的左上角坐標和 translationX和 translationY值的累計和

alpha:它表示View對象的alpha透明度,默認值是1(不透明),0代表完全透明(不可見)

由以上可知,視圖動畫所實現的動畫效果,在這裡基本都已經包含了,那麼如果一個屬性沒有get,set方法,屬性動畫是不是就束手無策了答案當然是否定的,google在應用層提供了兩種方案來解決這個問題, 一個是通過自定義一個屬性類或者包裝類,來間接地給這個屬性增加get方法:或者通過ValusAnimator來實現,ValusAnimator在後面的內容中會講到, 這裡先來看看如何使用包裝類的方法給一個屬性增加set,get方法:

 private static class WrapperView {

        private View mTarget;

        public WrapperView(View target) {
            mTarget = target;
        }

        public int getWidth() {
            return mTarget.getLayoutParams().width;
        }

        public void setWidth(int width) {
            mTarget.getLayoutParams().width = width;
            mTarget.requestLayout();
        }
    }

通過上面的代碼就給一個屬性包裝上了一層,並且提供lset,get方法,使用時操作就行了

WrapperView vi = new WrapperView(alpha);
ObjectAnimator.ofInt(vi,"width",500).setDuration(2000).start();

2.PropertyValuesHolder

這個類類似視圖動畫中的AnimationSet,就是把動畫給組合起來,在屬性動畫中,如果針對一個對象的多個屬性,就同時需要多個動畫了,可以使用PropertyValuesHolder,來實現,比如需要在平移的過程中,同時改變x,y的縮放,可以這樣實現

PropertyValuesHolder pvh1 = PropertyValuesHolder.ofFloat("translationX",300f);
PropertyValuesHolder pvh2 = PropertyValuesHolder.ofFloat("scaleX",1f,0,1f);
PropertyValuesHolder pvh3 = PropertyValuesHolder.ofFloat("scaleY",1f,0,1f);        ObjectAnimator.ofPropertyValuesHolder(alpha,pvh1,pvh2,pvh3).setDuration(2000).start();

3.ValueAnimator

ValueAnimator這個屬性在動畫當中有很大的地位,雖然不想ObjectAnimator那樣,耀眼,但是他確實屬性動畫的核心所在,ObjectAnimator也是繼承自他

public final class ObjectAnimator extends ValueAnimator

ValueAnimator本身不提供任何動畫,他更像是一個數值發生器,用來產生一定具有規律的數字,從而讓調用者控制動畫的整個過程,我們舉個例子來說明

ValueAnimator va = ValueAnimator.ofFloat(0,100);
                va.setTarget(value);
                va.setDuration(2000).start();
                va.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                    @Override
                    public void onAnimationUpdate(ValueAnimator animation) {
                        float values = (float) animation.getAnimatedValue();
                        Log.i("數值",values+"");
                    }
                });

我們運行一下

這裡寫圖片描述

4.動畫事件的監聽

一個完整的動畫是具有,start,repeat,end,cancel四個過程的,通過Android的接口,我們很容易監聽到這幾個事件

 ob.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) {

                    }
                });

當然,大部分的場景嗎,我們只關心動畫結束,所以,Android也提供了一個AnimatorLisistenerAdapter來讓你自己選擇監聽事件

va.addListener(new AnimatorListenerAdapter() {
                    @Override
                    public void onAnimationEnd(Animator animation) {
                        super.onAnimationEnd(animation);
                    }
                });

5.AnimatorSet

對於一個屬性同時作用在一個view上,前面已經有一個PropertyValuesHolder了,而AnimatorSet不僅能實現,而且能更精准的控制順序,同樣是實現PropertyValuesHolder的動畫,AnimatorSet是這樣實現的

        ObjectAnimator animator1 = ObjectAnimator.ofFloat(alpha, "translationX", 300f);
        ObjectAnimator animator2 = ObjectAnimator.ofFloat(alpha, "scaleX", 1f, 0, 1f);
        ObjectAnimator animator3 = ObjectAnimator.ofFloat(alpha, "scaleY", 1f, 0, 1f);
        AnimatorSet set = new AnimatorSet();
        set.setDuration(2000);
        set.playTogether(animator1,animator2,animator3);
        set.start();

在屬性動畫中,AnimatorSet正是通過playTogether等方法控制多個動畫協同工作,從而控制播放順序的

6.在XML中定義動畫

屬性動畫同樣的可以定義在xml中,我們也去玩玩


在代碼中引用


    /**
     * 引用xml動畫
     * @param v
     */
    private void scaleX(View v){
        Animator anim = AnimatorInflater
                .loadAnimator(this,R.animator.animator);
        anim.setTarget(v);
        anim.start();
    }

7.View的animate方法

在Android3.0,Google給view增加了animate方法直接來驅動屬性動畫,代碼如下,我們可以發現,其實animate就是屬性動畫的一種縮寫

 animate.animate().alpha(0).y(300).setDuration(2000).withStartAction(new Runnable() {
                    @Override
                    public void run() {

                    }
                }).withEndAction(new Runnable() {
                    @Override
                    public void run() {
                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {

                            }
                        });
                    }
                }).start();

三.Android布局動畫

所謂的布局動畫,就是作用在ViewGruop中給View添加的過渡效果,最簡單的方法是在xml中打開

 android:animateLayoutChanges="true"

不過這都是Android自帶的效果,渣渣

我們還可以通過LayoutAnimationController來定義

        ll = (LinearLayout) findViewById(R.id.ll);
        //設置過渡動畫
        ScaleAnimation sa = new ScaleAnimation(0, 1, 0, 1);
        sa.setDuration(2000);
        LayoutAnimationController lc = new LayoutAnimationController(sa, 0.5f);
        lc.setOrder(LayoutAnimationController.ORDER_NORMAL);
        //設置布局動畫
        ll.setLayoutAnimation(lc);

通過上面。就可以給布局正加一個視圖動畫,讓子View出現的時候有一個縮放動畫,在apiDemo中這個例子還是很經典的

LayoutAnimationController.ORDER_NORMAL 順序 LayoutAnimationController.ORDER_RANDOM 隨機 LayoutAnimationController.ORDER_REVEESE 反序

四.Interpolators(插值器)

插值器在動畫中是一個非常重要的概念,我們通過插值器可以定義動畫變換速率,這一點非常類似物理中的加速度,其作用主要是目標變化對應的變化,同樣的一個動畫變換起始值,在不同的插值器的作用下,每個單位時間內所達到的變換值都是不一樣的,例如一個平移動畫,如果使用線性插值器,那麼在持續時間內單位時間所移動的距離都是一樣的,如果使用加速度插值器,那麼單位時間內所移動的速度越來越快,大家如果把插值器的概念理解為一個人進行萬米長跑,規定一個小時到達,有的人怕時間來不及一開始就加速跑但是到後面速度越來越慢,而有的人開始節省體力,所以開始跑的比較慢,後來越跑越快直到終點,不管怎麼跑,最終他們的都是在規定的時間到達終點,唯一不同的是他們的跑的速度不同,通過這個例子,我們可以很好的理解插值器的概念

這裡寫圖片描述

五.自定義動畫

創建自定義動畫很簡單,只需要實現applyTransformation的邏輯就可以,不過通常情況下,我們還要覆蓋父類的initialize方法來完成一些初始化工作,

@Override
    protected void applyTransformation(float interpolatedTime, Transformation t) {
        super.applyTransformation(interpolatedTime, t);
    }

第一個參數interpolatedTime是前面說的插值器的時間因子,這個因子是由動畫當前完成的百分比和當前時間對應的差值計算的,取值范圍在0-1.0,第二個參數就非常簡單了,她是矩陣的封裝類,一般使用這個類獲取當前的矩陣對象,代碼如下

 Matrix matrix = t.getMatrix();

通過改變獲得的matrix 對象,可以將動畫效果實現,而對於matrix 的變換操作,基本上可以實現任何效果,我們實現一個電視機關閉的效果

 @Override
    protected void applyTransformation(float interpolatedTime, Transformation t) {

        Matrix matrix = t.getMatrix();
        matrix.preScale(1, 1 - interpolatedTime, width,height);
        super.applyTransformation(interpolatedTime, t);
    }

當然我們可以設置更加精准的插值器,,從而對不同的過程采用不同的動畫效果,模擬的更加逼真

接下來我們結合矩陣,並且使用Canmera來實現一個3D的效果,要注意的是,這裡所指的Camera不是相機,而是這個類,他封裝了openGl的3D動畫,我們繼續用代碼來實現

  @Override
    public void initialize(int width, int height, int parentWidth, int parentHeight) {

        super.initialize(width, height, parentWidth, parentHeight);
        setDuration(2000);
        setFillAfter(true);
        setInterpolator(new BounceInterpolator());
        w = width / 2;
        h = height / 2;

    }

    @Override
    protected void applyTransformation(float interpolatedTime, Transformation t) {

        Matrix matrix = t.getMatrix();
    //  matrix.preScale(1, 1 - interpolatedTime, w,h);
        mCamera.save();
        //設置旋轉角度
        mCamera.rotate(0, 180, 360);
        mCamera.restore();
        //通過pre方法設置矩形作用前的偏移量來改變旋轉中心
        matrix.preTranslate(w, h);
        matrix.postTranslate(-w, -h);

        super.applyTransformation(interpolatedTime, t);

    }

通過以上的方法,就可以實現了

六.Android 5.X SVG矢量動畫機制

黑科技來了,Google在Android5.X中增加了對SVG矢量圖形的支持,這對於創造新的高效率動畫具有很深遠的意義,首先,我們來了解一下什麼是SVG

可伸縮矢量圖形定義用於網絡的基於矢量的圖形使用xml格式定義圖形圖片在放大或者改變尺寸的情況下其圖形質量不會有所損失萬維網聯盟的標准與諸多DOM和XSL之類的W3C標准是一個整體

SVG在web上應用非常廣泛,在Android5.X之前的Android版本上,大家可以通過一些第三方庫在Android中使用SVG,而在Android5.X後,Android中添加了對< path >標簽的支持,從而讓開發者可以使用SVG來創建更加豐富的動畫效果,那麼SVG對傳統的Bitmap,究竟有什麼好處呢?bitmap通過每個像素點上存儲色彩信息來表達圖像,而SVG是一個繪圖標准,與之相對,最大的優勢是SVG放大不會失真,而且bitmap需要不同分辨率適配,SVG不需要

1.< path >標簽

使用< path >標簽來創建SVG,就是用指令的方式來控制一支畫筆,列入,移動畫筆來到某一個坐標位置,畫一條線,畫一條曲線,結束,< path >標簽所支持的指令大致有一下幾種

M = moveto(M X,Y):將畫筆移動到指定的坐標位置,但未發生繪制

L = lineto(L X,Y):畫直線到指定的位置

H = horizontal lineto( H X):畫水平線到指定的X坐標位置

V = vertical lineto(V Y ):畫垂直線到指定的Y坐標

C = curveto(C ,X1,Y1,X2,Y2,ENDX,ENDY):三次貝塞爾曲線

S = smooth curveto(S X2,Y2,ENDX,ENDY):三次貝塞爾曲線

Q = quadratic Belzier curve(Q X Y,ENDX,ENDY):二次貝塞爾曲線

T = smooth quadratic Belzier curvrto(T,ENDX,ENDY):映射前面路徑的重點

A = elliptical Are(A RX,RY,XROTATION,FLAG1FLAG2,X,Y):弧線

Z = closepath() 關閉路徑

使用上面的指令時,需要注意的幾點

坐標軸以(0,0)位中心,X軸水平向右,Y軸水平向下所有指令大小寫均可,大寫絕對定位,參照全局坐標系,小寫相對定位,參照父容器坐標系指令和數據間的空格可以無視同一指令出現多次可以用一個

2.SVG常見指令

L

繪制直線的指令是“L”,代表從當前點繪制直線到給定點,“L”之後的參數是一個點坐標,如“L 200 400”繪制直線,同時,還可以使用“H”和“V”指令來繪制水平豎直線,後面的參數是x坐標個y坐標

M

M指令類似Android繪圖中的path類moveto方法,即代表畫筆移動到某一點,但並不發生繪圖動作

A

A指令是用來繪制一條弧線,且允許弧線不閉合,可以把A指令繪制的弧度想象成橢圓的某一段A指令一下有七個指令

RX,RY指所有的橢圓的半軸大小 XROTATION 指橢圓的X軸和水平方向順時針方向的夾角,可以想象成一個水平的橢圓饒中心點順時針旋轉XROTATION 的角度 FLAG1 只有兩個值,1表示大角度弧度,0為小角度弧度 FLAG2 只有兩個值,確定從起點到終點的方向1順時針,0逆時針 X,Y為終點坐標

SVG的指令參數非常的復雜,但是再Android中,不需要繪制太多的SVG圖像,後面會有幾個小案例

3.SVG編輯器

SVG參數的寫法固定而且復雜,因此完全可以使用程序來實現,所以一般通過SVG編輯器來編輯SVG圖像,網上有很多在線的編輯器,通過可視化編輯圖像之後,點擊view source可以轉換成SVG代碼

下載離線的SVG編輯器,由很多強大的功能,這裡就不一一贅述了

這裡寫圖片描述

4.Android中使用SVG

Google在Android5.X後給我們提供了兩個新的API來支持SVG

VectorDrawable

AnimatedVectorDrawable

其中,VectorDrawable可以讓你創建基於XML的SVG圖像,並且結合AnimatedVectorDrawable來實現動畫效果

-1 VectorDrawable

在XML中創建一個靜態的SVG,通過這個結構

這裡寫圖片描述




這個代碼之中包含了兩組高寬,width,和height是表示SVG圖像的具體大小,後面的是表示SVG圖像劃分的比例,後面再繪制path時所使用的參數,就是根據這兩個值來進行轉換的,比如上面的代碼,將200dp劃分100份,如果在繪圖中使用坐標(50,50),則意味著該坐標為正中間,現在我們加上path標簽




    
        

    

通過添加< path>標簽繪制一個SVG齊總pathData就是圖形所用到的指令了,先用M指令,將畫筆移動到(25 , 50)的位置,再通過A指令來繪制一個圓弧並且填充他,通過以上代碼,就可以繪制一個SVG圖形了

\

填充指令


-2 AnimatedVectorDrawable

AnimatedVectorDrawable的作用是給VectorDrawable提供動畫效果,Google的工程師將AnimatedVectorDrawable比喻一個膠水,通過AnimatedVectorDrawable來連接靜態的VectorDrawable和動態的objectAnimator

下面我們來看看具體是怎麼樣來做的,首先我們在xml中定義一個< animated-vector>,來申明對AnimatedVectorDrawable的使用,並且指明是作用在path或者group上



    

    

對應的vector即為靜態的VectorDrawable




    

        

        

    

需要注意的是,AnimatedVectorDrawable中指明的target和name屬性,必須與VectorDrawable中需要的name保持一致,這樣系統能找到找到要實現的動畫元素,最後,通過AnimatedVectorDrawable中的target和animation屬性,將一個動畫作用在對應的name上,objectanimator代碼如下


最後,我們看到的,對動畫效果的實現,還是通過屬性動畫來完成的,只是屬性稍有不同

在< group>標簽和< path>標簽中添加rotation,fillColor,pathData屬性,那麼在objecyAnimator中,就可以通過指定,android:valueFrom=XXX,和android:property=”XXX”屬性,控制動畫的起始值,唯一需要注意的是,如果指定屬性為pathData,那麼需要添加一個屬性android:valueType-“pathType”來告訴系統進行pathData變換,類似的情況,可以使用rotation來進行旋轉變換,使用fileColor實現變換顏色,使用pathData進行形狀,位置的變換

當所有的XML准備好之後,我們就可以直接給一個imageview設置背景了




    

在程序中,我們只要使用這個start方法開啟動畫就可以‘

這裡寫圖片描述

在初步了解SVG動畫之後,我們來寫幾個實際的小例子來見識一下SVG的強大

5.SVG動畫實例

-1 線圖動畫

在android5.X之後,Google大量引入了線圖動畫,當頁面發生改變的時候,頁面的icon不再是生硬的切換,而是通過非常生動的動畫,轉換成另一種形態

要實現這樣的一個效果,我們首先要創建一個SVG圖形,即動態的VectorDrawable
我們要實現的效果就是上下兩根線,然後他們形成一個X的效果

path1和path2分別繪制了兩條直線




    
        

        

    

path1和path2分別繪制了一條直線,

這裡寫圖片描述

每條線都有三個點控制,接下來就是變換的動畫了


在以上代碼中,定義了一個pathType動畫,並且指定了起點,中點,終點

android:valueFrom="M 20, 80 L 50 , 80 80 ,80"
android:valueTo="M 20 ,80 L 50 ,50 80 ,80"

這兩個值是對應的起始點,不過需要注意的是,SVG的路徑變換屬性動畫中,變換前後階段屬必須相同,這也是前面需要使用的三個點看來繪制一條直線的原因,,有了VectorDrawable和objectAnimator,現在只需要AnimatedVectorDrawable將他們加起來就起來





    


    

針對trick這樣的一個VectorDrawable中的path1和path2的路徑,分別使用了objectAnimator,最後只需要去啟動動畫就可以了

package com.lgl.animations;

import android.graphics.drawable.Animatable;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.ImageView;

/**
 * 繪制SVG
 * Created by LGL on 2016/4/16.
 */
public class SVGActivity extends AppCompatActivity {

    private ImageView iv;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_svg);

        iv = (ImageView) findViewById(R.id.iv);
        iv.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

            }
        });
    }

    private void anim() {
        Drawable drawable = iv.getDrawable();
        if (drawable instanceof Animatable) {
            ((Animatable) drawable).start();
        }
    }

}


-2 模擬三球儀

三球儀是天體文學中的星象儀器,用來模擬地球,月亮和太陽的運行軌跡,如圖

這裡寫圖片描述

我們也來實現以下




    

        

        

            


            
                

            

        
    

這裡寫圖片描述

可以從代碼沖發現,sun在這個group中,有一個earth的group,我們這裡再定義一個動畫


後面的跟前面提到的差不多,就不寫了

-3.軌跡動畫

android對SVG的支持帶來了很多的特效,我們來做一個搜索的放大鏡效果吧,先定義好軌跡




    

    


這裡寫圖片描述

後面動畫的部分就不詳細寫了,受開發環境的限制,有興趣的可以拿著原書研究下

七.android動畫特效

通過前面的學習,我們基本掌握了android中的各種動畫了,所以,在這裡做幾個小例子

1.衛星菜單

當點擊小紅點的時候,彈出菜單,並且帶有一個緩沖的效果,這就是Google在MD中強調的動畫過渡,要怎麼實現這個動畫呢,其實還不是就一個開始一個結束動畫,看代碼

 /**
     * 執行動畫
     */
    private void statAnim(){
        ObjectAnimator animator0 = ObjectAnimator.ofFloat(iv0,"alpha",1F,0.5F);
        ObjectAnimator animator1 = ObjectAnimator.ofFloat(iv1,"translationY",200F);
        ObjectAnimator animator2 = ObjectAnimator.ofFloat(iv2,"translationX",200F);
        ObjectAnimator animator3 = ObjectAnimator.ofFloat(iv3,"translationY",-200F);
        ObjectAnimator animator4 = ObjectAnimator.ofFloat(iv4,"translationX",-200F);
        AnimatorSet set = new AnimatorSet();
        set.setInterpolator(new BounceInterpolator());
        set.playTogether(animator0,animator1,animator2,animator3,animator4);
        set.start();
        mFlag = false;
    }

下面就是點擊事件

iv0.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                   if (mFlag){
                       statAnim();
                   }else{
                       closeAnim();
                   }
            }
        });

2.計時器動畫

通過這個示例,我們了解一下ValueAnimator的效果,當用戶點擊後,數字不斷增加,好的,我們開始

package com.lgl.animations;

import android.animation.ValueAnimator;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.TextView;

/**
 * 繪制SVG
 * Created by LGL on 2016/4/16.
 */
public class SVGActivity extends AppCompatActivity {

    private TextView tv;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_svg);

        tv = (TextView) findViewById(R.id.tv);
        tv.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                tvTimer(tv);
            }
        });
    }

    private void  tvTimer(final  View view){
        ValueAnimator va = ValueAnimator.ofInt(0,100);
        va.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                ( (TextView)view).setText("$"+(Integer)animation.getAnimatedValue());
            }
        });
        va.setDuration(3000);
        va.start();
    }

}


我們來運行一下

這裡寫圖片描述

3.下拉展開動畫

下面我們來實現一個展開的動畫,首先,XML是這樣的




    

        

        

    

    

        

        

    

為了區分兩個不同的線性布局,我們給他設置了不同的顏色背景,好的,我們開始實現

package com.lgl.animations;

import android.animation.ValueAnimator;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;

/**
 * 下拉展開動畫
 * Created by LGL on 2016/4/18.
 */
public class AnimaActivity extends AppCompatActivity {

    private LinearLayout mHiddenView;
    private float mDensity;
    private int mHiddenViewMeasuredHeight;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_anima);

        mHiddenView = (LinearLayout) findViewById(R.id.hidden_view);
        //獲取像素密度
        mDensity = getResources().getDisplayMetrics().density;
        //獲取布局的高度
        mHiddenViewMeasuredHeight = (int) (mDensity*40+0.5);
    }

    public  void llClick(View view){
        if (mHiddenView.getVisibility() == View.GONE){
            animOpen(mHiddenView);
        }else{
            animClose(mHiddenView);
        }
    }

    private void animOpen(final  View view){
        view.setVisibility(View.VISIBLE);
        ValueAnimator va = createDropAnim(view,0,mHiddenViewMeasuredHeight);
        va.start();
    }


    private void animClose(final  View view){
        int origHeight = view.getHeight();
        ValueAnimator va = createDropAnim(view,origHeight,0);
        va.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                view.setVisibility(View.GONE);
            }
        });
        va.start();
    }


    private ValueAnimator createDropAnim(final  View view,int start,int end) {
        ValueAnimator va = ValueAnimator.ofInt(start, end);
        va.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                int value = (int) animation.getAnimatedValue();
                ViewGroup.LayoutParams layoutParams = view.getLayoutParams();
                layoutParams.height = value;
                view.setLayoutParams(layoutParams);
            }
        });
        return  va;
    }

}

好的,我們開始運行一下

這裡寫圖片描述

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved