1.介紹
Android系統爲我們提供了三種動畫效果的實現方式:
補間動畫(Tween Animation):只能對View進行動畫操作,支持移動、旋轉、透明、縮放四種效果,有一定的侷限性。
逐幀動畫(Frame Animation):把一個動畫分成多張圖片,然後把這些圖片連貫起來播放,原理和動畫片類似。
屬性動畫(Property Animation):通過改變對象的屬性值來實現的動畫效果,不侷限使用在View上。
由於補間動畫的侷限性,Android團隊在3.0版本中引入了屬性動畫,它的功能相當強大,彌補了補間動畫的不足,幾乎可以完全替代補間動畫了。
如果你想在自定義控件的某一個點上使用動畫,給View設置一個平滑的顏色過渡,或者使用3D旋轉動畫,那麼屬性動畫一定是你最佳的選擇,下面就讓我們一起來看看屬性動畫的基本用法吧。
2.ValueAnimator
ValueAnimator是整個屬性動畫機制中最核心的一個類,因爲屬性動畫就是通過不斷的改變對象的屬性值來實現的動畫效果,初始值和結束值之間的動畫過渡就是由ValueAnimator這個類來完成計算的。
ValueAnimator的用法還是比較簡單的,比如想要把一個值從0平滑的過渡到1,間隔300ms,就可以這樣寫:
ValueAnimator animator = ValueAnimator.ofFloat(0f, 1f);
animator.setDuration(300);
animator.start();
三行代碼搞定,是不是很簡單,但是這樣運行起來是看不出任何效果的,還需要加上一個監聽器:
ValueAnimator animator = ValueAnimator.ofFloat(0f, 1f);
animator.setDuration(300);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float currentValue = (float) animation.getAnimatedValue();
Log.i("onAnimationUpdate", "currentValue:" + currentValue);
}
});
animator.start();
運行一下,看下打印:
可以看到ValueAnimator幫我們計算了從0到1的過渡值,ofFloat方法是可以傳入多個參數的,比如在1s內,從0過渡到6,再過渡到3,然後再過渡到10,就可以這樣寫:
ValueAnimator animator = ValueAnimator.ofFloat(0f, 6f, 3f, 10f);
animator.setDuration(1000);
animator.start();
如果你不想要小數值過渡的話,還可以使用ofInt方法,使用和ofFloat方法相同,ValueAnimator中比較常用的就是ofFloat和oFInt方法了,還有一個ofObject,我會在下篇文章中講解。
可以看到上述代碼中,可以設置動畫的播放時間,除此之外還有一些常見的功能:
// 設置動畫的重複次數
// 直接傳入int型數值,INFINITE代表無限循環
animator.setRepeatCount(ValueAnimator.INFINITE);
// 設置動畫的重複模式
// RESTART代表重新播放,REVERSE代表倒序播放
animator.setRepeatMode(ValueAnimator.RESTART);
animator.setRepeatMode(ValueAnimator.REVERSE);
// 設置動畫的延遲播放時間
animator.setStartDelay(1000);
3.ObjectAnimator
與ValueAnimator相比ObjectAnimator纔是我們最常用到的類,ObjectAnimator繼承於ValueAnimator,其內部的動畫機制是依靠ValueAnimator來完成的,由於是繼承關係,在ObjectAnimator中也可以使用ValueAnimator中的一些方法,兩者的用法也很類似,下面就讓我們來看看ObjectAnimator的一些常見用法。
移動
把一張圖片沿X軸向右移動100px,然後向左移動回到原位:
// 沿X軸向移動100px,然後向左移動回到原位
// 沿Y軸移動,ofFloat第二個參數傳入translationY
ObjectAnimator animator = ObjectAnimator.ofFloat(image, "translationX", 0f, 100f, 0f);
// 動畫執行時長2s,默認300ms
animator.setDuration(2000);
animator.start();
3D旋轉
把一張圖片垂直旋轉360度:
// 垂直旋轉360度
// 水平旋轉,ofFloat第二個參數傳入rotationX
ObjectAnimator animator = ObjectAnimator.ofFloat(image, "rotationY", 0f, 360f);
animator.setDuration(2000);
animator.start();
透明
把一張圖片的透明度從0調節到1:
// 透明度從0到1
ObjectAnimator animator = ObjectAnimator.ofFloat(image, "alpha", 0f, 1f);
animator.setDuration(2000);
animator.start();
縮放
把一張圖片水平縮放0.5倍,然後恢復:
// 水平縮放0.5倍,然後恢復
// 垂直縮放,ofFloat第二個參數傳入scaleY
ObjectAnimator animator = ObjectAnimator.ofFloat(image, "scaleX", 1f, 0.5f, 1f);
animator.setDuration(2000);
animator.start();
屬性動畫中圖片的移動是實現了圖片真正意義上的移動,改變位置後可以點擊,與此相比,補間動畫只是改變了圖片的顯示效果,移動後不能點擊,這也是屬性動畫和補間動畫的一個重要區別。
ofFloat方法的第二個參數可以傳入任意對象的屬性名,ObjectAnimator內部的工作原理就是通過在View中查找屬性名對應的get、set方法來設置對應的屬性值的。
通俗的來講,就是假如屬性名是alpha,ObjectAnimator就會在ImageView中查找getAlpha方法和setAlpha方法,然後進行透明度設置的。
4.組合動畫
組合動畫需要藉助AnimatorSet這個類來完成,AnimatorSet提供了play(Animator anim)方法,傳入Animator對象之後返回一個AnimatorSet.Builder實例,AnimatorSet.Builder中有下面幾個方法:
with(Animator anim):將現有的動畫和傳入的動畫同時執行。
before(Animator anim):將現有的動畫在傳入的動畫之前執行。
after(Animator anim):將現有的動畫在傳入的動畫之後執行。
after(long delay):將現有的動畫延時執行。
舉個栗子:
// 圖片從屏幕左側移動到右側,再回到原位,同時透明度從0調節到1,然後垂直旋轉360度
ObjectAnimator trans = ObjectAnimator.ofFloat(image, "translationX", -100f, 100f, 0f);
ObjectAnimator alpha = ObjectAnimator.ofFloat(image, "alpha", 0f, 1f);
ObjectAnimator rotation = ObjectAnimator.ofFloat(image, "rotationY", 0f, 360f);
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.play(trans).with(alpha).before(rotation);
animatorSet.setDuration(5000);
animatorSet.start();
5.使用xml編寫動畫
在res目錄下創建一個animator文件夾,然後新建一個屬性動畫的xml文件,xml中可以使用如下三種標籤:
animator:對應代碼中的ValueAnimator類。
objectAnimator:對應代碼中的ObjectAnimator類。
set:對應代碼中的AnimatorSet類。
以上面的組合動畫爲例,使用xml來編寫下:
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:ordering="sequentially">
<set android:ordering="together">
<set android:ordering="sequentially">
<objectAnimator
android:duration="2000"
android:propertyName="translationX"
android:valueFrom="-100"
android:valueTo="100"
android:valueType="floatType" />
<objectAnimator
android:duration="2000"
android:propertyName="translationX"
android:valueFrom="100"
android:valueTo="0"
android:valueType="floatType" />
</set>
<objectAnimator
android:duration="2000"
android:propertyName="alpha"
android:valueFrom="0"
android:valueTo="1"
android:valueType="floatType" />
</set>
<objectAnimator
android:duration="2000"
android:propertyName="rotationY"
android:valueFrom="0"
android:valueTo="360"
android:valueType="floatType" />
</set>
ordering屬性可以設置爲sequentially(順序執行)、together(同時執行)。
在代碼中調用:
// 圖片從屏幕左側移動到右側,再回到原位,同時透明度從0調節到1,然後垂直旋轉360度
Animator animator = AnimatorInflater.loadAnimator(this, R.animator.combine);
animator.setTarget(image);
animator.start();
6.寫在最後
Ok,到這裏屬性動畫的基本用法就講完了,在下篇文章中我會寫一些屬性動畫的高級用法,敬請期待!
源碼已託管到GitHub上,歡迎Fork,覺得還不錯就Start一下吧!
GitHub地址:https://github.com/alidili/PropertyAnimationDemo
歡迎同學們吐槽評論,如果你覺得本篇博客對你有用,那麼就留個言或者頂一下吧(^-^)