Android中的動畫實現

android開發中用到的動畫實現方式有三種,即View動畫、Drawable動畫以及屬性動畫三種動畫的實現方式,關於這些動畫的實現方式網上很多文章都總結的很詳細了,寫這篇文章完全是爲了自己總結記錄,而且本文不會去追究代碼細節的問題,就單單總結下怎麼用的問題,具體代碼細節的話,請參考本文的參考文獻。

1、View動畫

View動畫的實現是通過View控件的setAnimation來設置動畫,可以設置的動畫有限,只有以下四種

  • AlphaAnimation: 透明度動畫
  • RotateAnimation: 旋轉動畫
  • ScaleAnimation: 縮放動畫
  • TranslateAnimation: 平移動畫

四種動畫的作用看名字應該就清楚了,這裏以RotateAnimation爲例來說說使用View動畫的兩種方式

第一種是通過xml的方式來實現(三種動畫實現方式都可以通過xml配置的方式來實現),在res/anim目錄下創建一個view_animation_rotate.xml 內容如下

<!--   
  * android:fromDegrees="-50":動畫開始執行時的控件起始狀態的角度;  
  * android:toDegrees="360":動畫結束執行時的控件結束狀態的角度;  
  * android:pivotX="50%":旋轉動畫的中心點的X軸方向的橫座標,Value正值(例如50%)時,意思是相對於控件的原始位置往右方向的50%控件寬度的位置爲橫座標,  
  *                         若Value爲負值(例如-50%),則表示往左方向;當Value爲數值時,則代表相對於屏幕的(px)像素值;  
  * android:pivotY="50%":旋轉動畫的中心店的Y軸方向的縱座標,原理同上;  
  * android:startOffset="1000":動畫執行前的延遲時間;  
  * android:fillAfter="true":當Valuetrue,表示動畫執行結束後停留在結束後的狀態;  
  * android:duration="2500":設置每一次動畫持續的時間值,單位爲毫秒(ms);  
  * android:repeatCount="5":設置動畫重複的次數;  
  * android:repeatMode="reverse":設置動畫重複的模式:  
  *     reverse0.0 -> 1.0 -> 0.0,動畫反覆執行;  
  *     restart0.0 -> 1.0, 0.0 -> 1.0,動畫每次都重新開始執行  
-->  

<rotate xmlns:android="http://schemas.android.com/apk/res/android"  
   android:interpolator="@android:anim/accelerate_decelerate_interpolator"  
   android:fromDegrees="520"  
   android:toDegrees="3600"  
   android:pivotX="50%"  
   android:pivotY="50%"  
   android:startOffset="1000"  
   android:fillAfter="true"  
   android:duration="2500"  
   android:repeatCount="4"  
   android:repeatMode="reverse"  
/> 

定義好xml後,便可通過AnimationUtils類來加載xml生成一個動畫對象,注意這個AnimationUtils類不是我們自己定義的類,而是Android Sdk提供的android.view.animation包中的類。

/** 
* xml文件加載圖片旋轉(Rotate)動畫 
*/  
RotateAnimation mAnimation = AnimationUtils.loadAnimation(this, R.anim.view_animation_rotate); 

這裏生成了一個RotateAnimation的對象,調用view.setAnimation(mAnimation)便設置好了view控件的動畫。

當然另外一種實現ViewAnimation的方法就是直接通過new RotateAnimation的方式實現,並且在新建的時候傳入基本動畫參數。

/** 
* 代碼創建圖片旋轉(Rotate)動畫 
* mAnimation = new RotateAnimation(fromDegrees, toDegrees, pivotXType, pivotXValue, pivotYType, pivotYValue); 
* fromDegrees:動畫開始執行時的控件起始狀態的角度; 
* toDegrees:動畫結束執行時的控件結束狀態的角度; 
* pivotXType:動畫在X軸相對於物件位置類型 ,分爲RELATIVE_TO_SELF、RELATIVE_TO_PARENT和ABSOLUTE三種類型: 
*                       1、RELATIVE_TO_SELF:相對於控件自身; 
*                       2、RELATIVE_TO_PARENT:相對於父控件; 
*                       3、ABSOLUTE:絕對座標; 
* pivotXValue:動畫開始執行時X軸方向的的起始位置,當位置類型爲RELATIVE_TO_SELF時,Value取0.0f~1.0f之間,當位置類型爲RELATIVE_TO_PARENT或ABSOLUTE時,Value使用(px)像素值; 
* pivotYType:動畫在Y軸相對於物件位置類型 ,分爲RELATIVE_TO_SELF、RELATIVE_TO_PARENT和ABSOLUTE三種類型; 
* pivotYValue:旋轉動畫的中心點的Y軸方向的縱座標,原理同上; 
*/  
//mAnimation = new RotateAnimation(fromDegrees, toDegrees)  
//mAnimation = new RotateAnimation(fromDegrees, toDegrees, pivotX, pivotY)  
RotateAnimation mAnimation = new RotateAnimation(-50f, 360f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
mAnimation.setDuration(2000);

到這類兩種實現View動畫的方式就說清楚了,當然我們可能有將四種View動畫方式結合起來使用,這個需求也好辦,可通過AnimationSet這個動畫集合類來實現,也可以在通過在res/anim目錄下的xml文件中配置多個動畫的方式來實現,這裏就不展開說明了。

2、Drawable動畫

Drawable動畫名稱來自於實現Drawable動畫的xml文件時放在res/drawable目錄中的,比如我們要實現一個機器人走動的動畫,那麼便可在drawable中放置機器人走動的圖片

這裏寫圖片描述

然後在res/drawable下創建drawable_animation_robot.xml文件,內容如下

<animation-list xmlns:android="http://schemas.android.com/apk/res/android"  
    android:oneshot="false">  
    <item android:drawable="@drawable/drawable_animation01" android:duration="80"/>  
    <item android:drawable="@drawable/drawable_animation02" android:duration="80"/>  
    <item android:drawable="@drawable/drawable_animation03" android:duration="80"/>  
    <item android:drawable="@drawable/drawable_animation04" android:duration="80"/>  
    <item android:drawable="@drawable/drawable_animation05" android:duration="80"/>  
    <item android:drawable="@drawable/drawable_animation06" android:duration="80"/>  
    <item android:drawable="@drawable/drawable_animation07" android:duration="80"/>  
    <item android:drawable="@drawable/drawable_animation08" android:duration="80"/>  
    <item android:drawable="@drawable/drawable_animation09" android:duration="80"/>  
    <item android:drawable="@drawable/drawable_animation10" android:duration="80"/>  
    <item android:drawable="@drawable/drawable_animation11" android:duration="80"/>  
    <item android:drawable="@drawable/drawable_animation12" android:duration="80"/>  
    <item android:drawable="@drawable/drawable_animation13" android:duration="80"/>  
    <item android:drawable="@drawable/drawable_animation14" android:duration="80"/>  
    <item android:drawable="@drawable/drawable_animation15" android:duration="80"/>  
    <item android:drawable="@drawable/drawable_animation16" android:duration="80"/>  
</animation-list>

設置好xml後,便可通過下面代碼去獲得Drawable動畫

//設置背景  
view.setBackgroundResource(R.drawable.drawable_animation_robot);  

//獲取當前的背景  
mAnimationDrawable = (AnimationDrawable) view.getBackground(); 

通過以下代碼便可以開啓動畫或者關閉動畫

//開啓動畫
mAnimationDrawable.start();

//關閉動畫
mAnmationDrawable.stop();

到這類Drawable動畫就算是說清楚了。

3、屬性動畫

屬性動畫是三種動畫實現裏最複雜的也是最靈活的,它通過去設置控件的屬性從而實現動畫效果,與屬性動畫相關且的有以下一些類

  • ObjectAnimator: 動畫執行類
  • ValueAnimator: 動畫執行類
  • AnimatorSet: 用於控制一組動畫的執行
  • AnimatorInflater : 用戶加載屬性動畫xml文件
  • TypeEvaluator: 類型估值器
  • TimeInteplotor:時間插值器

上面的這些類在實現屬性動畫時會被經常用到,下面來進行分別講解。

3.1 ObjectAnimator 、 ValueAnimator 、 AnimatorSet這幾個類的使用

從以上類中可以看出動畫執行類主要有兩個,分別是ObjectAnimator和ValueAnimator,其主要區別在於ObjectAnimator在實現動畫的時候需要首先指定動畫屬性,而ValueAnimator則不需要,ValueAnimator是在addUpdateListener中通過set方法去指定屬性。

ObjectAnimator實現動畫

ObjectAnimator  
.ofFloat(view, "rotationY", 0.0F, 360.0F)//指定了屬性rotationY
.setDuration(500)
.start();

ValueAnimator實現動畫

ValueAnimator animator = ValueAnimator.ofFloat(0, mScreenHeight - mBlueBall.getHeight());  
animator.setTarget(mBlueBall);  
animator.setDuration(1000).start();  
animator.addUpdateListener(new AnimatorUpdateListener()  
{  
    @Override  
    public void onAnimationUpdate(ValueAnimator animation)  
    {   
        //在addUpdateListener中通過set方法指定屬性
        mBlueBall.setTranslationY((Float) animation.getAnimatedValue());  
    }  
}); 

這裏我們看到無論是使用ObjectAnimator還是ValueAnimator這裏都是對一個屬性進行的動畫操作,那麼如果要同時操作幾個屬性動畫呢?當然我們可以使用AnimatorSet類去實現,但是如果我們不使用AnimatorSet類呢?

針對ObjectAnimator可以使用addUpdateListener的方式實現

ObjectAnimator anim = ObjectAnimator
        .ofFloat(view, "zhy", 1.0F,  0.0F)
        .setDuration(500);
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);  
    }  
});  

這裏的缺點很明顯,就是三個屬性,我們設置的變化參數卻只有一個,於是針對ObjectAnimator我們可以使用PropertyValuesHolder類來完成多屬性動畫操作,來解決這個問題

PropertyValuesHolder pvhX = PropertyValuesHolder.ofFloat("alpha", 1f, 0f, 1f);  
PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat("scaleX", 1f, 0, 1f);  
PropertyValuesHolder pvhZ = PropertyValuesHolder.ofFloat("scaleY", 1f, 0, 1f);  
ObjectAnimator.ofPropertyValuesHolder(view, pvhX, pvhY,pvhZ).setDuration(1000).start();  

這裏針對多屬性,便可以有有多個變化參數去設置動畫效果。

ValueAnimator實現多屬性動畫操作同樣的可以使用addUpdateListener以及PropertyValuesHolder兩種方法。

當然實現多屬性動畫操作,還可以使用AniamtorSet這個類來實現

AnimatorSet實現動畫集合

使用AnimatorSet這個類可以規定動畫的執行先後順序,各自的執行時間等,使用起來特別靈活

float cx = mBlueBall.getX();  
ObjectAnimator anim1 = ObjectAnimator.ofFloat(mBlueBall, "scaleX", 1.0f, 2f);  
ObjectAnimator anim2 = ObjectAnimator.ofFloat(mBlueBall, "scaleY", 1.0f, 2f);  
ObjectAnimator anim3 = ObjectAnimator.ofFloat(mBlueBall, "x",  cx ,  0f);  
ObjectAnimator anim4 = ObjectAnimator.ofFloat(mBlueBall, "x", cx);  

/** 
 * anim1,anim2,anim3同時執行 
 * anim4接着執行 
 */  
AnimatorSet animSet = new AnimatorSet();  
animSet.play(anim1).with(anim2);  
animSet.play(anim2).with(anim3);  
animSet.play(anim4).after(anim3);  
animSet.setDuration(1000);  
animSet.start();  

3.2 AnimatorInflater類的使用

前面講View動畫和Drawable動畫的時候都提到了xml來實現動畫的方式,而屬性動畫也可以通過xml的方式下來實現動畫效果,其就是藉助了AnimatorInflater這個類來實現。

AnimatorInflater類加載額xml文件放在res/animator/目錄下,這裏創建一個rotation.xml文件,內容爲

<?xml version="1.0" encoding="utf-8"?>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android" 
    android:propertyName="rotationX"
    android:duration="1000"
    android:valueType="floatType"
    android:valueFrom="0.0"
    android:valueTo="360.0">
</objectAnimator>

然後藉助AnimatorInflater類來加載xml動畫

Animator animator = AnimatorInflater.loadAnimator(context, R.animator.rotation);
animator.setTarget(view);
animator.setDuration(2000);
animator.setInterpolator(new LinearInterpolator());
animator.start();

這樣便通過使用AnimatorInflater加載xml完成了一個屬性動畫的操作。

3.3 TypeEvaluator 、 TimeInterpolator這兩個類的使用

前面提到TypeEvaluator叫做類型估值器,TimeInterpolator叫做時間插值器,類型估值器用來動態的設置屬性變化,而時間插值器用來設置時間相對動畫的變化效果。簡單的說,TimeInterpolator控制動畫的速度,而TypeEvaluator控制動畫的值。這兩個類的使用比較靈活,可以去參考模擬自然動畫的精髓——TimeInterpolator與TypeEvaluator這篇文章,這裏舉一個模擬拋物線的動畫來進行說明。

如果我希望小球拋物線運動【實現拋物線的效果,水平方向100px/s,垂直方向加速度200px/s*s 】,分析一下,貌似只和時間有關係,但是根據時間的變化,橫向和縱向的移動速率是不同的,我們該咋實現呢?此時就要重寫TypeEvaluator了,因爲我們在時間變化的同時,需要返回給對象兩個值,x當前位置,y當前位置。

ValueAnimator valueAnimator = new ValueAnimator();  
valueAnimator.setDuration(3000);  
valueAnimator.setObjectValues(new PointF(0, 0));  
valueAnimator.setInterpolator(new LinearInterpolator());  
valueAnimator.setEvaluator(new TypeEvaluator<PointF>()  
{  
    // fraction = t / duration  
    @Override  
    public PointF evaluate(float fraction, PointF startValue, PointF endValue)  
    {  
        Log.e(TAG, fraction * 3 + "");  
        // x值爲200 * t ,而y值爲0.5 * 10 * t * t  
        PointF point = new PointF();  
        point.x = 200 * fraction * 3;  
        point.y = 0.5f * 10 * (fraction * 3) * (fraction * 3);  
        return point;  
    }  
});  

valueAnimator.start();  
valueAnimator.addUpdateListener(new AnimatorUpdateListener()  
{  
    @Override  
    public void onAnimationUpdate(ValueAnimator animation)  
    {  
        PointF point = (PointF) animation.getAnimatedValue();  
        mBlueBall.setX(point.x);  
        mBlueBall.setY(point.y);  

    }  
}); 

從代碼可以看出重新定義了類型估值器,設置了x y值得變化,同時將時間插值器設置爲默認的線性變化,那麼最終小球將以拋物線的動畫運動。

4、參考文獻

本文基本代碼都是從其它參考文獻拷貝過來,略加修改的,感謝這些作者的辛勤奉獻。

1、 Android 屬性動畫(Property Animation) 完全解析 (上)

2、Android中的View動畫和屬性動畫

3、Android動畫之一:Drawable Animation

4、Android 動畫學習(一)之View Animation

5、 Android屬性動畫–基礎使用

6、模擬自然動畫的精髓——TimeInterpolator與TypeEvaluator

7、Android動畫,一篇就夠

8、res下的anim和animator文件夾

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章