1.介紹
Android系統(tǒng)為我們提供了三種動(dòng)畫效果的實(shí)現(xiàn)方式:
補(bǔ)間動(dòng)畫(Tween Animation):只能對(duì)View進(jìn)行動(dòng)畫操作,支持移動(dòng)洼畅、旋轉(zhuǎn)吩案、透明、縮放四種效果帝簇,有一定的局限性徘郭。
逐幀動(dòng)畫(Frame Animation):把一個(gè)動(dòng)畫分成多張圖片,然后把這些圖片連貫起來播放丧肴,原理和動(dòng)畫片類似残揉。
屬性動(dòng)畫(Property Animation):通過改變對(duì)象的屬性值來實(shí)現(xiàn)的動(dòng)畫效果,不局限使用在View上芋浮。
由于補(bǔ)間動(dòng)畫的局限性抱环,Android團(tuán)隊(duì)在3.0版本中引入了屬性動(dòng)畫,它的功能相當(dāng)強(qiáng)大纸巷,彌補(bǔ)了補(bǔ)間動(dòng)畫的不足镇草,幾乎可以完全替代補(bǔ)間動(dòng)畫了。
如果你想在自定義控件的某一個(gè)點(diǎn)上使用動(dòng)畫瘤旨,給View設(shè)置一個(gè)平滑的顏色過渡梯啤,或者使用3D旋轉(zhuǎn)動(dòng)畫,那么屬性動(dòng)畫一定是你最佳的選擇存哲,下面就讓我們一起來看看屬性動(dòng)畫的基本用法吧因宇。
2.ValueAnimator
ValueAnimator是整個(gè)屬性動(dòng)畫機(jī)制中最核心的一個(gè)類七婴,因?yàn)閷傩詣?dòng)畫就是通過不斷的改變對(duì)象的屬性值來實(shí)現(xiàn)的動(dòng)畫效果,初始值和結(jié)束值之間的動(dòng)畫過渡就是由ValueAnimator這個(gè)類來完成計(jì)算的察滑。
ValueAnimator的用法還是比較簡(jiǎn)單的本姥,比如想要把一個(gè)值從0平滑的過渡到1,間隔300ms杭棵,就可以這樣寫:
ValueAnimator animator = ValueAnimator.ofFloat(0f, 1f);
animator.setDuration(300);
animator.start();
三行代碼搞定婚惫,是不是很簡(jiǎn)單,但是這樣運(yùn)行起來是看不出任何效果的魂爪,還需要加上一個(gè)監(jiān)聽器:
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();
運(yùn)行一下先舷,看下打印:
可以看到ValueAnimator幫我們計(jì)算了從0到1的過渡值滓侍,ofFloat方法是可以傳入多個(gè)參數(shù)的蒋川,比如在1s內(nèi),從0過渡到6撩笆,再過渡到3捺球,然后再過渡到10,就可以這樣寫:
ValueAnimator animator = ValueAnimator.ofFloat(0f, 6f, 3f, 10f);
animator.setDuration(1000);
animator.start();
如果你不想要小數(shù)值過渡的話夕冲,還可以使用ofInt方法氮兵,使用和ofFloat方法相同,ValueAnimator中比較常用的就是ofFloat和oFInt方法了歹鱼,還有一個(gè)ofObject泣栈,我會(huì)在下篇文章中講解。
可以看到上述代碼中弥姻,可以設(shè)置動(dòng)畫的播放時(shí)間南片,除此之外還有一些常見的功能:
// 設(shè)置動(dòng)畫的重復(fù)次數(shù)
// 直接傳入int型數(shù)值,INFINITE代表無限循環(huán)
animator.setRepeatCount(ValueAnimator.INFINITE);
// 設(shè)置動(dòng)畫的重復(fù)模式
// RESTART代表重新播放庭敦,REVERSE代表倒序播放
animator.setRepeatMode(ValueAnimator.RESTART);
animator.setRepeatMode(ValueAnimator.REVERSE);
// 設(shè)置動(dòng)畫的延遲播放時(shí)間
animator.setStartDelay(1000);
3.ObjectAnimator
與ValueAnimator相比ObjectAnimator才是我們最常用到的類疼进,ObjectAnimator繼承于ValueAnimator,其內(nèi)部的動(dòng)畫機(jī)制是依靠ValueAnimator來完成的秧廉,由于是繼承關(guān)系伞广,在ObjectAnimator中也可以使用ValueAnimator中的一些方法,兩者的用法也很類似定血,下面就讓我們來看看ObjectAnimator的一些常見用法赔癌。
移動(dòng)
把一張圖片沿X軸向右移動(dòng)100px,然后向左移動(dòng)回到原位:
// 沿X軸向移動(dòng)100px澜沟,然后向左移動(dòng)回到原位
// 沿Y軸移動(dòng),ofFloat第二個(gè)參數(shù)傳入translationY
ObjectAnimator animator = ObjectAnimator.ofFloat(image, "translationX", 0f, 100f, 0f);
// 動(dòng)畫執(zhí)行時(shí)長(zhǎng)2s峡谊,默認(rèn)300ms
animator.setDuration(2000);
animator.start();
3D旋轉(zhuǎn)
把一張圖片垂直旋轉(zhuǎn)360度:
// 垂直旋轉(zhuǎn)360度
// 水平旋轉(zhuǎn)茫虽,ofFloat第二個(gè)參數(shù)傳入rotationX
ObjectAnimator animator = ObjectAnimator.ofFloat(image, "rotationY", 0f, 360f);
animator.setDuration(2000);
animator.start();
透明
把一張圖片的透明度從0調(diào)節(jié)到1:
// 透明度從0到1
ObjectAnimator animator = ObjectAnimator.ofFloat(image, "alpha", 0f, 1f);
animator.setDuration(2000);
animator.start();
縮放
把一張圖片水平縮放0.5倍刊苍,然后恢復(fù):
// 水平縮放0.5倍,然后恢復(fù)
// 垂直縮放濒析,ofFloat第二個(gè)參數(shù)傳入scaleY
ObjectAnimator animator = ObjectAnimator.ofFloat(image, "scaleX", 1f, 0.5f, 1f);
animator.setDuration(2000);
animator.start();
屬性動(dòng)畫中圖片的移動(dòng)是實(shí)現(xiàn)了圖片真正意義上的移動(dòng)正什,改變位置后可以點(diǎn)擊,與此相比号杏,補(bǔ)間動(dòng)畫只是改變了圖片的顯示效果婴氮,移動(dòng)后不能點(diǎn)擊,這也是屬性動(dòng)畫和補(bǔ)間動(dòng)畫的一個(gè)重要區(qū)別盾致。
ofFloat方法的第二個(gè)參數(shù)可以傳入任意對(duì)象的屬性名主经,ObjectAnimator內(nèi)部的工作原理就是通過在View中查找屬性名對(duì)應(yīng)的get、set方法來設(shè)置對(duì)應(yīng)的屬性值的庭惜。
通俗的來講罩驻,就是假如屬性名是alpha,ObjectAnimator就會(huì)在ImageView中查找getAlpha方法和setAlpha方法护赊,然后進(jìn)行透明度設(shè)置的惠遏。
4.組合動(dòng)畫
組合動(dòng)畫需要借助AnimatorSet這個(gè)類來完成,AnimatorSet提供了play(Animator anim)方法骏啰,傳入Animator對(duì)象之后返回一個(gè)AnimatorSet.Builder實(shí)例节吮,AnimatorSet.Builder中有下面幾個(gè)方法:
with(Animator anim):將現(xiàn)有的動(dòng)畫和傳入的動(dòng)畫同時(shí)執(zhí)行。
before(Animator anim):將現(xiàn)有的動(dòng)畫在傳入的動(dòng)畫之前執(zhí)行判耕。
after(Animator anim):將現(xiàn)有的動(dòng)畫在傳入的動(dòng)畫之后執(zhí)行课锌。
after(long delay):將現(xiàn)有的動(dòng)畫延時(shí)執(zhí)行。
舉個(gè)栗子:
// 圖片從屏幕左側(cè)移動(dòng)到右側(cè)祈秕,再回到原位渺贤,同時(shí)透明度從0調(diào)節(jié)到1,然后垂直旋轉(zhuǎn)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編寫動(dòng)畫
在res目錄下創(chuàng)建一個(gè)animator文件夾请毛,然后新建一個(gè)屬性動(dòng)畫的xml文件志鞍,xml中可以使用如下三種標(biāo)簽:
animator:對(duì)應(yīng)代碼中的ValueAnimator類。
objectAnimator:對(duì)應(yīng)代碼中的ObjectAnimator類方仿。
set:對(duì)應(yīng)代碼中的AnimatorSet類固棚。
以上面的組合動(dòng)畫為例,使用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屬性可以設(shè)置為sequentially(順序執(zhí)行)仙蚜、together(同時(shí)執(zhí)行)此洲。
在代碼中調(diào)用:
// 圖片從屏幕左側(cè)移動(dòng)到右側(cè),再回到原位委粉,同時(shí)透明度從0調(diào)節(jié)到1呜师,然后垂直旋轉(zhuǎn)360度
Animator animator = AnimatorInflater.loadAnimator(this, R.animator.combine);
animator.setTarget(image);
animator.start();
6.寫在最后
Ok,到這里屬性動(dòng)畫的基本用法就講完了贾节,在下篇文章中我會(huì)寫一些屬性動(dòng)畫的高級(jí)用法汁汗,敬請(qǐng)期待衷畦!
源碼已托管到GitHub上,歡迎Fork知牌,覺得還不錯(cuò)就Start一下吧祈争!
GitHub地址:https://github.com/alidili/PropertyAnimationDemo
歡迎同學(xué)們吐槽評(píng)論,如果你覺得本篇博客對(duì)你有用角寸,那么就留個(gè)言或者點(diǎn)下喜歡吧(^-^)
《Android屬性動(dòng)畫(二) ValueAnimator的實(shí)際應(yīng)用 & 自定義TypeEvaluator》