android動(dòng)畫詳解
掃描二維碼
隨時(shí)隨地手機(jī)看文章
1 背景
不能只分析源碼呀,分析的同時(shí)也要整理歸納基礎(chǔ)知識(shí),剛好有人微博私信讓全面說說Android的動(dòng)畫,所以今天來一發(fā)Android應(yīng)用的各種Animation大集合。英文厲害的請(qǐng)直接移步參考Android Developer。
Android系統(tǒng)提供了很多豐富的API去實(shí)現(xiàn)UI的2D與3D動(dòng)畫,最主要的劃分可以分為如下幾類:
View Animation:?視圖動(dòng)畫在古老的Android版本系統(tǒng)中就已經(jīng)提供了,只能被用來設(shè)置View的動(dòng)畫。
Drawable Animation:?這種動(dòng)畫(也叫Frame動(dòng)畫、幀動(dòng)畫)其實(shí)可以劃分到視圖動(dòng)畫的類別,專門用來一個(gè)一個(gè)的顯示Drawable的resources,就像放幻燈片一樣。
Property Animation:?屬性動(dòng)畫只對(duì)Android 3.0(API 11)以上版本的Android系統(tǒng)才有效,這種動(dòng)畫可以設(shè)置給任何Object,包括那些還沒有渲染到屏幕上的對(duì)象。這種動(dòng)畫是可擴(kuò)展的,可以讓你自定義任何類型和屬性的動(dòng)畫。
可以看見,當(dāng)前應(yīng)用程序開發(fā)涉及的主要?jiǎng)赢嬕簿瓦@三大類,我們接下來以類別為基礎(chǔ)來慢慢展開說明。
2 View Animation(視圖動(dòng)畫)使用詳解 2-1 視圖動(dòng)畫概述
視圖動(dòng)畫,也叫Tween(補(bǔ)間)動(dòng)畫可以在一個(gè)視圖容器內(nèi)執(zhí)行一系列簡(jiǎn)單變換(位置、大小、旋轉(zhuǎn)、透明度)。譬如,如果你有一個(gè)TextView對(duì)象,您可以移動(dòng)、旋轉(zhuǎn)、縮放、透明度設(shè)置其文本,當(dāng)然,如果它有一個(gè)背景圖像,背景圖像會(huì)隨著文本變化。
補(bǔ)間動(dòng)畫通過XML或Android代碼定義,建議使用XML文件定義,因?yàn)樗呖勺x性、可重用性。
如下是視圖動(dòng)畫相關(guān)的類繼承關(guān)系:
AlphaAnimation?放置在res/anim/目錄下
漸變透明度動(dòng)畫效果
RotateAnimation?放置在res/anim/目錄下
畫面轉(zhuǎn)移旋轉(zhuǎn)動(dòng)畫效果
ScaleAnimation?放置在res/anim/目錄下
漸變尺寸伸縮動(dòng)畫效果
TranslateAnimation?放置在res/anim/目錄下
畫面轉(zhuǎn)換位置移動(dòng)動(dòng)畫效果
AnimationSet?放置在res/anim/目錄下
一個(gè)持有其它動(dòng)畫元素alpha、scale、translate、rotate或者其它set元素的容器
通過上圖和上表可以直觀的看出來補(bǔ)間動(dòng)畫的關(guān)系及種類了吧,接下來我們就詳細(xì)一個(gè)一個(gè)的介紹一下各種補(bǔ)間動(dòng)畫。
2-2 視圖動(dòng)畫詳細(xì)說明
可以看出來Animation抽象類是所有補(bǔ)間動(dòng)畫類的基類,所以基類會(huì)提供一些通用的動(dòng)畫屬性方法,如下我們就來詳細(xì)看看這些屬性
2-2-1 Animation屬性詳解android:detachWallpaper setDetachWallpaper(boolean) 是否在壁紙上運(yùn)行 android:duration setDuration(long) 動(dòng)畫持續(xù)時(shí)間,毫秒為單位 android:fillAfter setFillAfter(boolean) 控件動(dòng)畫結(jié)束時(shí)是否保持動(dòng)畫最后的狀態(tài) android:fillBefore setFillBefore(boolean) 控件動(dòng)畫結(jié)束時(shí)是否還原到開始動(dòng)畫前的狀態(tài) android:fillEnabled setFillEnabled(boolean) 與android:fillBefore效果相同 android:interpolator setInterpolator(Interpolator) 設(shè)定插值器(指定的動(dòng)畫效果,譬如回彈等) android:repeatCount setRepeatCount(int) 重復(fù)次數(shù) android:repeatMode setRepeatMode(int) 重復(fù)類型有兩個(gè)值,reverse表示倒序回放,restart表示從頭播放 android:startOffset setStartOffset(long) 調(diào)用start函數(shù)之后等待開始運(yùn)行的時(shí)間,單位為毫秒 android:zAdjustment setZAdjustment(int) 表示被設(shè)置動(dòng)畫的內(nèi)容運(yùn)行時(shí)在Z軸上的位置(top/bottom/normal),默認(rèn)為normal
也就是說,無(wú)論我們補(bǔ)間動(dòng)畫的哪一種都已經(jīng)具備了這種屬性,也都可以設(shè)置使用這些屬性中的一個(gè)或多個(gè)。
那接下來我們就看看每種補(bǔ)間動(dòng)畫特有的一些屬性說明吧。
2-2-2 Alpha屬性詳解android:fromAlpha AlphaAnimation(float fromAlpha, …) 動(dòng)畫開始的透明度(0.0到1.0,0.0是全透明,1.0是不透明) android:toAlpha AlphaAnimation(…, float toAlpha) 動(dòng)畫結(jié)束的透明度,同上 2-2-3 Rotate屬性詳解android:fromDegrees RotateAnimation(float fromDegrees, …) 旋轉(zhuǎn)開始角度,正代表順時(shí)針度數(shù),負(fù)代表逆時(shí)針度數(shù) android:toDegrees RotateAnimation(…, float toDegrees, …) 旋轉(zhuǎn)結(jié)束角度,正代表順時(shí)針度數(shù),負(fù)代表逆時(shí)針度數(shù) android:pivotX RotateAnimation(…, float pivotX, …) 縮放起點(diǎn)X坐標(biāo)(數(shù)值、百分?jǐn)?shù)、百分?jǐn)?shù)p,譬如50表示以當(dāng)前View左上角坐標(biāo)加50px為初始點(diǎn)、50%表示以當(dāng)前View的左上角加上當(dāng)前View寬高的50%做為初始點(diǎn)、50%p表示以當(dāng)前View的左上角加上父控件寬高的50%做為初始點(diǎn)) android:pivotY RotateAnimation(…, float pivotY) 縮放起點(diǎn)Y坐標(biāo),同上規(guī)律 2-2-4 Scale屬性詳解android:fromXScale ScaleAnimation(float fromX, …) 初始X軸縮放比例,1.0表示無(wú)變化 android:toXScale ScaleAnimation(…, float toX, …) 結(jié)束X軸縮放比例 android:fromYScale ScaleAnimation(…, float fromY, …) 初始Y軸縮放比例 android:toYScale ScaleAnimation(…, float toY, …) 結(jié)束Y軸縮放比例 android:pivotX ScaleAnimation(…, float pivotX, …) 縮放起點(diǎn)X軸坐標(biāo)(數(shù)值、百分?jǐn)?shù)、百分?jǐn)?shù)p,譬如50表示以當(dāng)前View左上角坐標(biāo)加50px為初始點(diǎn)、50%表示以當(dāng)前View的左上角加上當(dāng)前View寬高的50%做為初始點(diǎn)、50%p表示以當(dāng)前View的左上角加上父控件寬高的50%做為初始點(diǎn)) android:pivotY ScaleAnimation(…, float pivotY) 縮放起點(diǎn)Y軸坐標(biāo),同上規(guī)律 2-2-5 Translate屬性詳解android:fromXDelta TranslateAnimation(float fromXDelta, …) 起始點(diǎn)X軸坐標(biāo)(數(shù)值、百分?jǐn)?shù)、百分?jǐn)?shù)p,譬如50表示以當(dāng)前View左上角坐標(biāo)加50px為初始點(diǎn)、50%表示以當(dāng)前View的左上角加上當(dāng)前View寬高的50%做為初始點(diǎn)、50%p表示以當(dāng)前View的左上角加上父控件寬高的50%做為初始點(diǎn)) android:fromYDelta TranslateAnimation(…, float fromYDelta, …) 起始點(diǎn)Y軸從標(biāo),同上規(guī)律 android:toXDelta TranslateAnimation(…, float toXDelta, …) 結(jié)束點(diǎn)X軸坐標(biāo),同上規(guī)律 android:toYDelta TranslateAnimation(…, float toYDelta) 結(jié)束點(diǎn)Y軸坐標(biāo),同上規(guī)律 2-2-6 AnimationSet詳解
AnimationSet繼承自Animation,是上面四種的組合容器管理類,沒有自己特有的屬性,他的屬性繼承自Animation,所以特別注意,當(dāng)我們對(duì)set標(biāo)簽使用Animation的屬性時(shí)會(huì)對(duì)該標(biāo)簽下的所有子控件都產(chǎn)生影響。
2-3 視圖動(dòng)畫使用方法
通過上面對(duì)于動(dòng)畫的屬性介紹之后我們來看看在Android中這些動(dòng)畫如何使用(PS:這里直接演示xml方式,至于java方式太簡(jiǎn)單了就不說了),如下
上面就是一個(gè)標(biāo)準(zhǔn)的使用我們定義的補(bǔ)間動(dòng)畫的模板。至于補(bǔ)間動(dòng)畫的使用,Animation還有如下一些比較實(shí)用的方法介紹:
reset() 重置Animation的初始化 cancel() 取消Animation動(dòng)畫 start() 開始Animation動(dòng)畫 setAnimationListener(AnimationListener listener) 給當(dāng)前Animation設(shè)置動(dòng)畫監(jiān)聽 hasStarted() 判斷當(dāng)前Animation是否開始 hasEnded() 判斷當(dāng)前Animation是否結(jié)束
既然補(bǔ)間動(dòng)畫只能給View使用,那就來看看View中和動(dòng)畫相關(guān)的幾個(gè)常用方法吧,如下:
...
ImageView?spaceshipImage?=?(ImageView)?findViewById(R.id.spaceshipImage); Animation?hyperspaceJumpAnimation?=?AnimationUtils.loadAnimation(this,?R.anim.hyperspace_jump); spaceshipImage.startAnimation(hyperspaceJumpAnimation);
startAnimation(Animation animation) 對(duì)當(dāng)前View開始設(shè)置的Animation動(dòng)畫 clearAnimation() 取消當(dāng)View在執(zhí)行的Animation動(dòng)畫
到此整個(gè)Android的補(bǔ)間動(dòng)畫常用詳細(xì)屬性及方法全部介紹完畢,如有特殊的屬性需求可以訪問Android Developer查閱即可。如下我們就來個(gè)綜合大演練。
2-4 視圖動(dòng)畫注意事項(xiàng)
關(guān)于視圖動(dòng)畫(補(bǔ)間動(dòng)畫)的例子我就不介紹了,網(wǎng)上簡(jiǎn)直多的都泛濫了。只是強(qiáng)調(diào)在使用補(bǔ)間動(dòng)畫時(shí)注意如下一點(diǎn)即可:
特別特別注意:補(bǔ)間動(dòng)畫執(zhí)行之后并未改變View的真實(shí)布局屬性值。切記這一點(diǎn),譬如我們?cè)贏ctivity中有一個(gè)Button在屏幕上方,我們?cè)O(shè)置了平移動(dòng)畫移動(dòng)到屏幕下方然后保持動(dòng)畫最后執(zhí)行狀態(tài)呆在屏幕下方,這時(shí)如果點(diǎn)擊屏幕下方動(dòng)畫執(zhí)行之后的Button是沒有任何反應(yīng)的,而點(diǎn)擊原來屏幕上方?jīng)]有Button的地方卻響應(yīng)的是點(diǎn)擊Button的事件。
2-5 視圖動(dòng)畫Interpolator插值器詳解 2-5-1 插值器簡(jiǎn)介
介紹補(bǔ)間動(dòng)畫插值器之前我們先來看一幅圖,如下:
可以看見其實(shí)各種插值器都是實(shí)現(xiàn)了Interpolator接口而已,同時(shí)可以看見系統(tǒng)提供了許多已經(jīng)實(shí)現(xiàn)OK的插值器,具體如下:
AccelerateDecelerateInterpolator @android:anim/accelerate_decelerate_interpolator 動(dòng)畫始末速率較慢,中間加速 AccelerateInterpolator @android:anim/accelerate_interpolator 動(dòng)畫開始速率較慢,之后慢慢加速 AnticipateInterpolator @android:anim/anticipate_interpolator 開始的時(shí)候從后向前甩 AnticipateOvershootInterpolator @android:anim/anticipate_overshoot_interpolator 類似上面AnticipateInterpolator BounceInterpolator @android:anim/bounce_interpolator 動(dòng)畫結(jié)束時(shí)彈起 CycleInterpolator @android:anim/cycle_interpolator 循環(huán)播放速率改變?yōu)檎仪€ DecelerateInterpolator @android:anim/decelerate_interpolator 動(dòng)畫開始快然后慢 LinearInterpolator @android:anim/linear_interpolator 動(dòng)畫勻速改變 OvershootInterpolator @android:anim/overshoot_interpolator 向前彈出一定值之后回到原來位置 PathInterpolator ? 新增,定義路徑坐標(biāo)后按照路徑坐標(biāo)來跑。
如上就是系統(tǒng)提供的一些插值器,下面我們來看看怎么使用他們。
2-5-2 插值器使用方法
插值器的使用比較簡(jiǎn)單,如下:
...
2-5-3 插值器的自定義
有時(shí)候你會(huì)發(fā)現(xiàn)系統(tǒng)提供的插值器不夠用,可能就像View一樣需要自定義。所以接下來我們來看看插值器的自定義,關(guān)于插值器的自定義分為兩種實(shí)現(xiàn)方式,xml自定義實(shí)現(xiàn)(其實(shí)就是對(duì)現(xiàn)有的插值器的一些屬性修改)或者java代碼實(shí)現(xiàn)方式。如下我們來說說。
先看看XML自定義插值器的步驟:
在res/anim/目錄下創(chuàng)建filename.xml文件。修改你準(zhǔn)備自定義的插值器。
在你的補(bǔ)間動(dòng)畫文件中引用該文件即可。
可以看見上面第二步修改的是現(xiàn)有插值器的一些屬性,但是有些插值器卻不具備修改屬性,具體如下:
無(wú)可自定義的attribute。
android:factor 浮點(diǎn)值,加速速率(默認(rèn)值為1)。
android:tension 浮點(diǎn)值,起始點(diǎn)后拉的張力數(shù)(默認(rèn)值為2)。
android:tension 浮點(diǎn)值,起始點(diǎn)后拉的張力數(shù)(默認(rèn)值為2)。?
android:extraTension 浮點(diǎn)值,拉力的倍數(shù)(默認(rèn)值為1.5)。
無(wú)可自定義的attribute。
android:cycles 整形,循環(huán)的個(gè)數(shù)(默認(rèn)為1)。
android:factor 浮點(diǎn)值,減速的速率(默認(rèn)為1)。
無(wú)可自定義的attribute。
android:tension 浮點(diǎn)值,超出終點(diǎn)后的張力(默認(rèn)為2)。
再來看看Java自定義插值器的(Java自定義插值器其實(shí)是xml自定義的升級(jí),也就是說如果我們修改xml的屬性還不能滿足需求,那就可以選擇通過Java來實(shí)現(xiàn))方式。
可以看見上面所有的Interpolator都實(shí)現(xiàn)了Interpolator接口,而Interpolator接口又繼承自TimeInterpolator,TimeInterpolator接口定義了一個(gè)float getInterpolation(float input);方法,這個(gè)方法是由系統(tǒng)調(diào)用的,其中的參數(shù)input代表動(dòng)畫的時(shí)間,在0和1之間,也就是開始和結(jié)束之間。
如下就是一個(gè)動(dòng)畫始末速率較慢、中間加速的AccelerateDecelerateInterpolator插值器:
public?class?AccelerateDecelerateInterpolator?extends?BaseInterpolator
????????implements?NativeInterpolatorFactory?{
????......
????public?float?getInterpolation(float?input)?{
????????return?(float)(Math.cos((input?+?1)?*?Math.PI)?/?2.0f)?+?0.5f;
????}
????......
}到此整個(gè)補(bǔ)間動(dòng)畫與補(bǔ)間動(dòng)畫的插值器都分析完畢了,接下來看下別的動(dòng)畫。
【工匠若水?http://blog.csdn.net/yanbober?轉(zhuǎn)載請(qǐng)注明出處。點(diǎn)我開始Android技術(shù)交流】
3 Drawable Animation(Drawable動(dòng)畫)使用詳解 3-1 Drawable動(dòng)畫概述
Drawable動(dòng)畫其實(shí)就是Frame動(dòng)畫(幀動(dòng)畫),它允許你實(shí)現(xiàn)像播放幻燈片一樣的效果,這種動(dòng)畫的實(shí)質(zhì)其實(shí)是Drawable,所以這種動(dòng)畫的XML定義方式文件一般放在res/drawable/目錄下。具體關(guān)于幀動(dòng)畫的xml使用方式翻墻點(diǎn)擊我查看,java方式翻墻點(diǎn)擊我查看。
如下圖就是幀動(dòng)畫的源碼文件:
可以看見實(shí)際的真實(shí)父類就是Drawable。
3-2 Drawable動(dòng)畫詳細(xì)說明
我們依舊可以使用xml或者java方式實(shí)現(xiàn)幀動(dòng)畫。但是依舊推薦使用xml,具體如下:
?必須是根節(jié)點(diǎn),包含一個(gè)或者多個(gè)元素,屬性有:
android:oneshot?true代表只執(zhí)行一次,false循環(huán)執(zhí)行。?類似一幀的動(dòng)畫資源。
?animation-list的子項(xiàng),包含屬性如下:
android:drawable?一個(gè)frame的Drawable資源。android:duration?一個(gè)frame顯示多長(zhǎng)時(shí)間。 3-3 Drawable動(dòng)畫實(shí)例演示
關(guān)于幀動(dòng)畫相對(duì)來說比較簡(jiǎn)單,這里給出一個(gè)常規(guī)使用框架,如下:
ImageView?rocketImage?=?(ImageView)?findViewById(R.id.rocket_image); rocketImage.setBackgroundResource(R.drawable.rocket_thrust); rocketAnimation?=?(AnimationDrawable)?rocketImage.getBackground(); rocketAnimation.start();
特別注意,AnimationDrawable的start()方法不能在Activity的onCreate方法中調(diào)運(yùn),因?yàn)锳nimationDrawable還未完全附著到window上,所以最好的調(diào)運(yùn)時(shí)機(jī)是onWindowFocusChanged()方法中。
至此幀動(dòng)畫也就說明完成了。讓我們接下來進(jìn)入Android更牛叉的動(dòng)畫類型。
4 Property Animation(屬性動(dòng)畫)使用詳解
在使用屬性動(dòng)畫之前先來看幾個(gè)常用的View屬性成員:
translationX,translationY:控制View的位置,值是相對(duì)于View容器左上角坐標(biāo)的偏移。rotationX,rotationY:控制相對(duì)于軸心旋轉(zhuǎn)。x,y:控制View在容器中的位置,即左上角坐標(biāo)加上translationX和translationY的值。alpha:控制View對(duì)象的alpha透明度值。
這幾個(gè)常用的屬性相信大家都很熟悉,接下來的屬性動(dòng)畫我們就從這里展開。
4-1 屬性動(dòng)畫概述
Android 3.0以后引入了屬性動(dòng)畫,屬性動(dòng)畫可以輕而易舉的實(shí)現(xiàn)許多View動(dòng)畫做不到的事,上面也看見了,View動(dòng)畫無(wú)非也就做那幾種事情,別的也搞不定,而屬性動(dòng)畫就可以的,譬如3D旋轉(zhuǎn)一張圖片。其實(shí)說白了,你記住一點(diǎn)就行,屬性動(dòng)畫實(shí)現(xiàn)原理就是修改控件的屬性值實(shí)現(xiàn)的動(dòng)畫。
具體先看下類關(guān)系:
/**
?*?This?is?the?superclass?for?classes?which?provide?basic?support?for?animations?which?can?be
?*?started,?ended,?and?have?AnimatorListeners?added?to?them.
?*/
public?abstract?class?Animator?implements?Cloneable?{
????......
}所有的屬性動(dòng)畫的抽象基類就是他。我們看下他的實(shí)現(xiàn)子類:?
?
其實(shí)可以看見,屬性動(dòng)畫的實(shí)現(xiàn)有7個(gè)類(PS,之所以類繼承關(guān)系列表會(huì)出來那么多是因?yàn)槲蚁螺d了所有版本的SDK,你只用關(guān)注我紅點(diǎn)標(biāo)注的就行,妹的,ubuntu下圖片處理工具怎么都這么難用),進(jìn)去粗略分析可以發(fā)現(xiàn),好幾個(gè)是hide的類,而其他可用的類繼承關(guān)系又如下:
ValueAnimator?放置在res/animator/目錄下
在一個(gè)特定的時(shí)間里執(zhí)行一個(gè)動(dòng)畫
TimeAnimator
不支持/點(diǎn)我查看原因
時(shí)序監(jiān)聽回調(diào)工具
ObjectAnimator?放置在res/animator/目錄下
一個(gè)對(duì)象的一個(gè)屬性動(dòng)畫
AnimatorSet?放置在res/animator/目錄下
動(dòng)畫集合
所以可以看見,我們平時(shí)使用屬性動(dòng)畫的重點(diǎn)就在于AnimatorSet、ObjectAnimator、TimeAnimator、ValueAnimator。所以接下來我們就來依次說說如何使用。
4-2 屬性動(dòng)畫詳細(xì)說明 4-2-1 屬性動(dòng)畫計(jì)算原理
參看Android官方文檔,英文原版詳情點(diǎn)我查看!
Android屬性動(dòng)畫(注意最低兼容版本,不過可以使用開源項(xiàng)目來替代低版本問題)提供了以下屬性:
Duration:動(dòng)畫的持續(xù)時(shí)間;TimeInterpolation:定義動(dòng)畫變化速率的接口,所有插值器都必須實(shí)現(xiàn)此接口,如線性、非線性插值器;TypeEvaluator:用于定義屬性值計(jì)算方式的接口,有int、float、color類型,根據(jù)屬性的起始、結(jié)束值和插值一起計(jì)算出當(dāng)前時(shí)間的屬性值;Animation sets:動(dòng)畫集合,即可以同時(shí)對(duì)一個(gè)對(duì)象應(yīng)用多個(gè)動(dòng)畫,這些動(dòng)畫可以同時(shí)播放也可以對(duì)不同動(dòng)畫設(shè)置不同的延遲;Frame refreash delay:多少時(shí)間刷新一次,即每隔多少時(shí)間計(jì)算一次屬性值,默認(rèn)為10ms,最終刷新時(shí)間還受系統(tǒng)進(jìn)程調(diào)度與硬件的影響;Repeat Country and behavoir:重復(fù)次數(shù)與方式,如播放3次、5次、無(wú)限循環(huán),可以讓此動(dòng)畫一直重復(fù),或播放完時(shí)向反向播放;
接下來先來看官方為了解釋原理給出的兩幅圖(其實(shí)就是初中物理題,不解釋):
?
上面就是一個(gè)線性勻速動(dòng)畫,描述了一個(gè)Object的X屬性運(yùn)動(dòng)動(dòng)畫,該對(duì)象的X坐標(biāo)在40ms內(nèi)從0移動(dòng)到40,每10ms刷新一次,移動(dòng)4次,每次移動(dòng)為40/4=10pixel。?
?
上面是一個(gè)非勻速動(dòng)畫,描述了一個(gè)Object的X屬性運(yùn)動(dòng)動(dòng)畫,該對(duì)象的X坐標(biāo)在40ms內(nèi)從0移動(dòng)到40,每10ms刷新一次,移動(dòng)4次,但是速率不同,開始和結(jié)束的速度要比中間部分慢,即先加速后減速。
接下來我們來詳細(xì)的看一下,屬性動(dòng)畫系統(tǒng)的重要組成部分是如何計(jì)算動(dòng)畫值的,下圖描述了如上面所示動(dòng)畫的實(shí)現(xiàn)作用過程。
其中的ValueAnimator是動(dòng)畫的執(zhí)行類,跟蹤了當(dāng)前動(dòng)畫的執(zhí)行時(shí)間和當(dāng)前時(shí)間下的屬性值;ValueAnimator封裝了動(dòng)畫的TimeInterpolator時(shí)間插值器和一個(gè)TypeEvaluator類型估值,用于設(shè)置動(dòng)畫屬性的值,就像上面圖2非線性動(dòng)畫里,TimeInterpolator使用了AccelerateDecelerateInterpolator、TypeEvaluator使用了IntEvaluator。
為了執(zhí)行一個(gè)動(dòng)畫,你需要?jiǎng)?chuàng)建一個(gè)ValueAnimator,并且指定目標(biāo)對(duì)象屬性的開始、結(jié)束值和持續(xù)時(shí)間。在調(diào)用start后,整個(gè)動(dòng)畫過程中, ValueAnimator會(huì)根據(jù)已經(jīng)完成的動(dòng)畫時(shí)間計(jì)算得到一個(gè)0到1之間的分?jǐn)?shù),代表該動(dòng)畫的已完成動(dòng)畫百分比。0表示0%,1表示100%,譬如上面圖一線性勻速動(dòng)畫中總時(shí)間 t = 40 ms,t = 10 ms的時(shí)候是 0.25。
當(dāng)ValueAnimator計(jì)算完已完成動(dòng)畫分?jǐn)?shù)后,它會(huì)調(diào)用當(dāng)前設(shè)置的TimeInterpolator,去計(jì)算得到一個(gè)interpolated(插值)分?jǐn)?shù),在計(jì)算過程中,已完成動(dòng)畫百分比會(huì)被加入到新的插值計(jì)算中。如上圖2非線性動(dòng)畫中,因?yàn)閯?dòng)畫的運(yùn)動(dòng)是緩慢加速的,它的插值分?jǐn)?shù)大約是 0.15,小于t = 10ms時(shí)的已完成動(dòng)畫分?jǐn)?shù)0.25。而在上圖1中,這個(gè)插值分?jǐn)?shù)一直和已完成動(dòng)畫分?jǐn)?shù)是相同的。
當(dāng)插值分?jǐn)?shù)計(jì)算完成后,ValueAnimator會(huì)根據(jù)插值分?jǐn)?shù)調(diào)用合適的 TypeEvaluator去計(jì)算運(yùn)動(dòng)中的屬性值。
好了,現(xiàn)在我們來看下代碼就明白這段話了,上面圖2非線性動(dòng)畫里,TimeInterpolator使用了AccelerateDecelerateInterpolator、TypeEvaluator使用了IntEvaluator。所以這些類都是標(biāo)準(zhǔn)的API,我們來看下標(biāo)準(zhǔn)API就能類比自己寫了,如下:
首先計(jì)算已完成動(dòng)畫時(shí)間分?jǐn)?shù)(以10ms為例):t=10ms/40ms=0.25。
接著看如下源碼如何實(shí)現(xiàn)計(jì)算差值分?jǐn)?shù)的:
public?class?AccelerateDecelerateInterpolator?extends?BaseInterpolator
????????implements?NativeInterpolatorFactory?{
????public?AccelerateDecelerateInterpolator()?{
????}
????......
????//這是我們關(guān)注重點(diǎn),可以發(fā)現(xiàn)如下計(jì)算公式計(jì)算后(input即為時(shí)間因子)插值大約為0.15。
????public?float?getInterpolation(float?input)?{
????????return?(float)(Math.cos((input?+?1)?*?Math.PI)?/?2.0f)?+?0.5f;
????}
????......
}其實(shí)AccelerateDecelerateInterpolator的基類接口就是TimeInterpolator,如下,他只有g(shù)etInterpolation方法,也就是上面我們關(guān)注的方法。
public?interface?TimeInterpolator?{
????float?getInterpolation(float?input);
}接著ValueAnimator會(huì)根據(jù)插值分?jǐn)?shù)調(diào)用合適的TypeEvaluator(IntEvaluator)去計(jì)算運(yùn)動(dòng)中的屬性值,如下,因?yàn)閟tartValue = 0,所以屬性值:0+0.15*(40-0)= 6。
public?class?IntEvaluator?implements?TypeEvaluator{
????public?Integer?evaluate(float?fraction,?Integer?startValue,?Integer?endValue)?{
????????int?startInt?=?startValue;
????????return?(int)(startInt?+?fraction?*?(endValue?-?startInt));
????}
}這就是官方給的一個(gè)關(guān)于屬性動(dòng)畫實(shí)現(xiàn)的過程及基本原理解釋,相信你看到這里是會(huì)有些迷糊的,沒關(guān)系,你先有個(gè)大致概念就行,接下來我們會(huì)慢慢進(jìn)入實(shí)戰(zhàn),因?yàn)锳ndroid的屬性動(dòng)畫相對(duì)于其他動(dòng)畫來說涉及的知識(shí)點(diǎn)本來就比較復(fù)雜,所以我們慢慢來。
4-2-2 XML方式屬性動(dòng)畫
在xml中可直接用的屬性動(dòng)畫節(jié)點(diǎn)有ValueAnimator、ObjectAnimator、AnimatorSet。如下是官方的一個(gè)例子和解釋(詳情點(diǎn)我):
...
屬性解釋:
android:ordering 控制子動(dòng)畫啟動(dòng)方式是先后有序的還是同時(shí)進(jìn)行。sequentially:動(dòng)畫按照先后順序;together(默認(rèn)):動(dòng)畫同時(shí)啟動(dòng);
屬性解釋:
android:propertyName String類型,必須要設(shè)置的節(jié)點(diǎn)屬性,代表要執(zhí)行動(dòng)畫的屬性(通過名字引用),辟如你可以指定了一個(gè)View的”alpha” 或者 “backgroundColor” ,這個(gè)objectAnimator元素沒有對(duì)外說明target屬性,所以你不能在XML中設(shè)置執(zhí)行這個(gè)動(dòng)畫,必須通過調(diào)用loadAnimator()方法加載你的XML動(dòng)畫資源,然后調(diào)用setTarget()應(yīng)用到具備這個(gè)屬性的目標(biāo)對(duì)象上(譬如TextView)。 android:valueTo float、int或者color類型,必須要設(shè)置的節(jié)點(diǎn)屬性,表明動(dòng)畫結(jié)束的點(diǎn);如果是顏色的話,由6位十六進(jìn)制的數(shù)字表示。 android:valueFrom 相對(duì)應(yīng)valueTo,動(dòng)畫的起始點(diǎn),如果沒有指定,系統(tǒng)會(huì)通過屬性的get方法獲取,顏色也是6位十六進(jìn)制的數(shù)字表示。 android:duration 動(dòng)畫的時(shí)長(zhǎng),int類型,以毫秒為單位,默認(rèn)為300毫秒。 android:startOffset 動(dòng)畫延遲的時(shí)間,從調(diào)用start方法后開始計(jì)算,int型,毫秒為單位。 android:repeatCount 一個(gè)動(dòng)畫的重復(fù)次數(shù),int型,”-1“表示無(wú)限循環(huán),”1“表示動(dòng)畫在第一次執(zhí)行完成后重復(fù)執(zhí)行一次,也就是兩次,默認(rèn)為0,不重復(fù)執(zhí)行。 android:repeatMode 重復(fù)模式:int型,當(dāng)一個(gè)動(dòng)畫執(zhí)行完的時(shí)候應(yīng)該如何處理。該值必須是正數(shù)或者是-1,“reverse”會(huì)使得按照動(dòng)畫向相反的方向執(zhí)行,可實(shí)現(xiàn)類似鐘擺效果。“repeat”會(huì)使得動(dòng)畫每次都從頭開始循環(huán)。 android:valueType 關(guān)鍵參數(shù),如果該value是一個(gè)顏色,那么就不需要指定,因?yàn)閯?dòng)畫框架會(huì)自動(dòng)的處理顏色值。有intType和floatType(默認(rèn))兩種:分別說明動(dòng)畫值為int和float型。
屬性解釋:?
同上屬性,不多介紹。
XML屬性動(dòng)畫使用方法:
AnimatorSet?set?=?(AnimatorSet)?AnimatorInflater.loadAnimator(myContext, ????R.animtor.property_animator); set.setTarget(myObject); set.start();
4-2-3 Java方式屬性動(dòng)畫
1、ObjectAnimator:繼承自ValueAnimator,允許你指定要進(jìn)行動(dòng)畫的對(duì)象以及該對(duì)象的一個(gè)屬性。該類會(huì)根據(jù)計(jì)算得到的新值自動(dòng)更新屬性。大多數(shù)的情況使用ObjectAnimator就足夠了,因?yàn)樗沟媚繕?biāo)對(duì)象動(dòng)畫值的處理過程變得足夠簡(jiǎn)單,不用像ValueAnimator那樣自己寫動(dòng)畫更新的邏輯,但是ObjectAnimator有一定的限制,比如它需要目標(biāo)對(duì)象的屬性提供指定的處理方法(譬如提供getXXX,setXXX方法),這時(shí)候你就需要根據(jù)自己的需求在ObjectAnimator和ValueAnimator中看哪種實(shí)現(xiàn)更方便了。
<pre style="font-family:'Source Code Pro', monospace;font-size:14px;l
| java類名 | xml關(guān)鍵字 | 描述信息 |
|---|---|---|
| xml屬性 | java方法 | 解釋 |
| xml屬性 | java方法 | 解釋 |
| xml屬性 | java方法 | 解釋 |
| xml屬性 | java方法 | 解釋 |
| xml屬性 | java方法 | 解釋 |
| Animation類的方法 | 解釋 | |
| View類的常用動(dòng)畫操作方法 | 解釋 | |
| java類 | xml id值 | 描述 |
| java類名 | xml關(guān)鍵字 | 描述信息 |
| xml屬性 | 解釋 | |
| xml屬性 | 解釋 |





