動(dòng)畫簡介
您可以通過動(dòng)畫添加視覺提示,向用戶通知應(yīng)用中的動(dòng)態(tài)。當(dāng)界面狀態(tài)發(fā)生改變時(shí)(例如有新內(nèi)容加載或有新操作可用時(shí)),動(dòng)畫尤其有用导帝。動(dòng)畫還為應(yīng)用增加了優(yōu)美的外觀,使其擁有更高品質(zhì)的外觀和風(fēng)格穿铆。
Android 根據(jù)您需要的動(dòng)畫類型提供不同的動(dòng)畫 API您单,因此本頁概括介紹了向界面添加動(dòng)作的不同方法。
屬性動(dòng)畫概述
屬性動(dòng)畫系統(tǒng)是一個(gè)強(qiáng)健的框架荞雏,用于為幾乎任何內(nèi)容添加動(dòng)畫效果虐秦。您可以定義一個(gè)隨時(shí)間更改任何對象屬性的動(dòng)畫,無論其是否繪制到屏幕上凤优。屬性動(dòng)畫會(huì)在指定時(shí)長內(nèi)更改屬性(對象中的字段)的值悦陋。要添加動(dòng)畫效果,請指定要添加動(dòng)畫效果的對象屬性别洪,例如對象在屏幕上的位置叨恨、動(dòng)畫效果持續(xù)多長時(shí)間以及要在哪些值之間添加動(dòng)畫效果。
借助屬性動(dòng)畫系統(tǒng)挖垛,您可以定義動(dòng)畫的以下特性:
- 時(shí)長:您可以指定動(dòng)畫的時(shí)長。默認(rèn)時(shí)長為 300 毫秒秉颗。
- 時(shí)間插值:您可以指定如何根據(jù)動(dòng)畫的當(dāng)前已播放時(shí)長來計(jì)算屬性的值痢毒。
- 重復(fù)計(jì)數(shù)和行為:您可以指定是否在某個(gè)時(shí)長結(jié)束后重復(fù)播放動(dòng)畫以及重復(fù)播放動(dòng)畫多少次。您還可以指定是否要反向播放動(dòng)畫蚕甥。如果將其設(shè)置為反向播放哪替,則會(huì)先播放動(dòng)畫,然后反向播放動(dòng)畫菇怀,直到達(dá)到重復(fù)次數(shù)凭舶。
- Animator 集:您可以將動(dòng)畫分成多個(gè)邏輯集,它們可以一起播放爱沟、按順序播放或者在指定的延遲時(shí)間后播放帅霜。
- 幀刷新延遲:您可以指定動(dòng)畫幀的刷新頻率。默認(rèn)設(shè)置為每 10 毫秒刷新一次呼伸,但應(yīng)用刷新幀的速度最終取決于整個(gè)系統(tǒng)的繁忙程度以及系統(tǒng)為底層計(jì)時(shí)器提供服務(wù)的速度身冀。
屬性動(dòng)畫的工作原理
首先,讓我們通過一個(gè)簡單的示例來了解動(dòng)畫的工作原理。圖 1 描繪了一個(gè)假設(shè)的對象搂根,該對象的 x 屬性(表示其在屏幕上的水平位置)添加了動(dòng)畫效果珍促。動(dòng)畫時(shí)長設(shè)置為 40 毫秒,要移動(dòng)的距離為 40 像素剩愧。該對象每隔 10 毫秒(這是默認(rèn)的幀刷新頻率)會(huì)水平移動(dòng) 10 像素猪叙。在 40 毫秒時(shí),動(dòng)畫停止仁卷,同時(shí)對象在水平位置 40 處停止沐悦。這是使用線性插值(表示對象以恒定速度移動(dòng))的動(dòng)畫示例。
也可以指定動(dòng)畫使用非線性插值五督。圖 2 展示了一個(gè)假設(shè)的對象藏否,它在動(dòng)畫開始時(shí)加速,在動(dòng)畫結(jié)束前減速充包。該對象仍在 40 毫秒內(nèi)移動(dòng)了 40 像素副签,但這種移動(dòng)是非線性的。開始時(shí)基矮,此動(dòng)畫加速移動(dòng)到中間點(diǎn)淆储,然后從中間點(diǎn)減速移動(dòng),直至動(dòng)畫結(jié)束家浇。如圖 2 所示本砰,動(dòng)畫在開頭和結(jié)尾移動(dòng)的距離小于在中間移動(dòng)的距離。
我們來詳細(xì)了解一下屬性動(dòng)畫系統(tǒng)的重要組成部分將如何計(jì)算如上所示的動(dòng)畫钢悲。圖 3 描繪了主類之間是如何相互協(xié)作的点额。
ValueAnimator對象跟蹤動(dòng)畫的時(shí)間,例如動(dòng)畫的已運(yùn)行時(shí)長以及正在添加動(dòng)畫效果的屬性的當(dāng)前值莺琳。
ValueAnimator 包含 TimeInterpolator和 TypeEvaluator还棱;前者用于定義動(dòng)畫插值,后者用于定義如何計(jì)算正在添加動(dòng)畫效果的屬性的值惭等。例如珍手,在圖 2 中,所用的 TimeInterpolator為 AccelerateDecelerateInterpolator辞做,所用的 TypeEvaluator 為 IntEvaluator琳要。
要開始動(dòng)畫,請創(chuàng)建一個(gè) ValueAnimator秤茅,并為您想要添加動(dòng)畫效果的屬性賦予起始值和結(jié)束值稚补,以及動(dòng)畫時(shí)長。當(dāng)您調(diào)用 start() 時(shí)嫂伞,動(dòng)畫即會(huì)開始播放孔厉。在整個(gè)動(dòng)畫播放期間拯钻,ValueAnimator 將基于動(dòng)畫時(shí)長和已播放時(shí)長計(jì)算已完成動(dòng)畫分?jǐn)?shù)(在 0 和 1 之間)。已完成動(dòng)畫分?jǐn)?shù)表示動(dòng)畫已完成時(shí)間的百分比撰豺,0 表示 0%粪般,1 表示 100%。以圖 1 為例污桦,在 t = 10ms 處亩歹,已完成動(dòng)畫分?jǐn)?shù)將為 0.25,因?yàn)榭倳r(shí)長 t = 40ms凡橱。
在 ValueAnimator 計(jì)算完已完成動(dòng)畫分?jǐn)?shù)后小作,它會(huì)調(diào)用當(dāng)前設(shè)置的TimeInterpolator 來計(jì)算插值分?jǐn)?shù)。插值分?jǐn)?shù)會(huì)將已完成動(dòng)畫分?jǐn)?shù)映射為一個(gè)新分?jǐn)?shù)稼钩,該分?jǐn)?shù)會(huì)考慮已設(shè)置的時(shí)間插值顾稀。例如,在圖 2 中坝撑,由于動(dòng)畫緩慢加速静秆,t = 10ms 時(shí)的插值分?jǐn)?shù)(約 0.15)小于已完成動(dòng)畫分?jǐn)?shù) (0.25)。在圖 1 中巡李,插值分?jǐn)?shù)始終等于已完成動(dòng)畫分?jǐn)?shù)抚笔。
計(jì)算插值分?jǐn)?shù)后,ValueAnimator 會(huì)調(diào)用相應(yīng)的 TypeEvaluator侨拦,以根據(jù)動(dòng)畫的插值分?jǐn)?shù)殊橙、起始值和結(jié)束值來計(jì)算要添加動(dòng)畫效果的屬性的值。例如狱从,在圖 2 中膨蛮,t = 10ms 時(shí)的插值分?jǐn)?shù)為 0.15,因此矫夯,此時(shí)屬性的值為 0.15 × (40 - 0)鸽疾,即 6。
屬性動(dòng)畫與試圖動(dòng)畫的區(qū)別
視圖動(dòng)畫系統(tǒng)僅提供為View對象添加動(dòng)畫效果的功能训貌,因此,如果您想為非 對象添加動(dòng)畫效果冒窍,則必須實(shí)現(xiàn)自己的代碼才能做到递沪。視圖動(dòng)畫系統(tǒng)也存在一些限制,因?yàn)樗鼉H公開 對象的部分方面來供您添加動(dòng)畫效果综液;例如款慨,您可以對視圖的縮放和旋轉(zhuǎn)添加動(dòng)畫效果,但無法對背景顏色這樣做谬莹。
視圖動(dòng)畫系統(tǒng)的另一個(gè)缺點(diǎn)是它只會(huì)在繪制視圖的位置進(jìn)行修改檩奠,而不會(huì)修改實(shí)際的視圖本身桩了。例如,如果您為某個(gè)按鈕添加了動(dòng)畫效果埠戳,使其可以在屏幕上移動(dòng)井誉,該按鈕會(huì)正確繪制,但能夠點(diǎn)擊按鈕的實(shí)際位置并不會(huì)更改整胃,因此您必須通過實(shí)現(xiàn)自己的邏輯來處理此事件颗圣。
有了屬性動(dòng)畫系統(tǒng),您就可以完全擺脫這些束縛屁使,還可以為任何對象(視圖和非視圖)的任何屬性添加動(dòng)畫效果在岂,并且實(shí)際修改的是對象本身。屬性動(dòng)畫系統(tǒng)在執(zhí)行動(dòng)畫方面也更為強(qiáng)健蛮寂。概括地講蔽午,您可以為要添加動(dòng)畫效果的屬性(例如顏色、位置或大谐晏!)分配 Animator及老,還可以定義動(dòng)畫的各個(gè)方面,例如多個(gè) Animator 的插值和同步除嘹。
不過写半,視圖動(dòng)畫系統(tǒng)的設(shè)置需要的時(shí)間較短,需要編寫的代碼也較少尉咕。如果視圖動(dòng)畫可以完成您需要執(zhí)行的所有操作叠蝇,或者現(xiàn)有代碼已按照您需要的方式運(yùn)行,則無需使用屬性動(dòng)畫系統(tǒng)年缎。在某些用例中悔捶,也可以針對不同的情況同時(shí)使用這兩種動(dòng)畫系統(tǒng)。
API 概述
類 | 說明 |
---|---|
ValueAnimator | 屬性動(dòng)畫的主計(jì)時(shí)引擎单芜,它也可計(jì)算要添加動(dòng)畫效果的屬性的值蜕该。它具有計(jì)算動(dòng)畫值所需的所有核心功能,同時(shí)包含每個(gè)動(dòng)畫的計(jì)時(shí)詳情洲鸠、有關(guān)動(dòng)畫是否重復(fù)播放的信息堂淡、用于接收更新事件的監(jiān)聽器以及設(shè)置待評估自定義類型的功能。為屬性添加動(dòng)畫效果分為兩個(gè)步驟:計(jì)算添加動(dòng)畫效果之后的值扒腕,以及對要添加動(dòng)畫效果的對象和屬性設(shè)置這些值绢淀。ValueAnimator 不會(huì)執(zhí)行第二個(gè)步驟,因此瘾腰,您必須監(jiān)聽由 ValueAnimator 計(jì)算的值的更新情況皆的,并使用您自己的邏輯修改要添加動(dòng)畫效果的對象。如需了解詳情蹋盆,請參閱使用 ValueAnimator 添加動(dòng)畫效果部分费薄。 |
ObjectAnimator | ValueAnimator的子類硝全,用于設(shè)置目標(biāo)對象和對象屬性以添加動(dòng)畫效果。此類會(huì)在計(jì)算出動(dòng)畫的新值后相應(yīng)地更新屬性楞抡。在大多數(shù)情況下伟众,您不妨使用 ObjectAnimator,因?yàn)樗梢詷O大地簡化對目標(biāo)對象的值添加動(dòng)畫效果這一過程拌倍。不過赂鲤,有時(shí)您需要直接使用 ValueAnimator,因?yàn)?ObjectAnimator存在其他一些限制柱恤,例如要求目標(biāo)對象具有特定的訪問器方法数初。 |
AnimatorSet | 此類提供一種將動(dòng)畫分組在一起的機(jī)制,以使它們彼此相對運(yùn)行梗顺。您可以將動(dòng)畫設(shè)置為一起播放泡孩、按順序播放或者在指定的延遲時(shí)間后播放。如需了解詳情寺谤,請參閱使用 AnimatorSet 編排多個(gè)動(dòng)畫部分仑鸥。 |
評估程序負(fù)責(zé)告知屬性動(dòng)畫系統(tǒng)如何計(jì)算指定屬性的值。它們使用由 Animator 類提供的計(jì)時(shí)數(shù)據(jù)(即動(dòng)畫的起始值和結(jié)束值)变屁,并根據(jù)這些數(shù)據(jù)計(jì)算屬性添加動(dòng)畫效果之后的值眼俊。屬性動(dòng)畫系統(tǒng)可提供以下評估程序:
類/接口 | 說明 |
---|---|
IntEvaluator | 這是用于計(jì)算 int 屬性的值的默認(rèn)評估程序。 |
FloatEvaluator | 這是用于計(jì)算 float 屬性的值的默認(rèn)評估程序粟关。 |
ArgbEvaluator | 這是用于計(jì)算顏色屬性的值(用十六進(jìn)制值表示)的默認(rèn)評估程序疮胖。 |
TypeEvaluator | 此接口用于創(chuàng)建您自己的評估程序。如果您要添加動(dòng)畫效果的對象屬性不是 int 闷板、float 或顏色澎灸,那么您必須實(shí)現(xiàn) TypeEvaluator 接口,才能指定如何計(jì)算對象屬性添加動(dòng)畫效果之后的值遮晚。如果您想以不同于默認(rèn)行為的方式處理 int 性昭、float 和顏色,您還可以為這些類型的值指定自定義 TypeEvaluator县遣。如需詳細(xì)了解如何編寫自定義評估程序糜颠,請參閱使用 TypeEvaluator 部分。 |
時(shí)間插值器指定了如何根據(jù)時(shí)間計(jì)算動(dòng)畫中的特定值萧求。例如括蝠,您可以指定動(dòng)畫在整個(gè)動(dòng)畫中以線性方式播放,即動(dòng)畫在整個(gè)播放期間勻速移動(dòng)饭聚;也可以指定動(dòng)畫使用非線性時(shí)間,例如動(dòng)畫在開始后加速并在結(jié)束前減速搁拙。表 3 介紹了 android.view.animation 中包含的插值器秒梳。如果下表提供的插值器都不能滿足您的需求法绵,請實(shí)現(xiàn) TimeInterpolator 接口并創(chuàng)建您自己的插值器。如需詳細(xì)了解如何編寫自定義插值器酪碘,請參閱 使用插值器 朋譬。
類/接口 | 說明 |
---|---|
AccelerateDecelerateInterpolator | 該插值器的變化率在開始和結(jié)束時(shí)緩慢但在中間會(huì)加快。 |
AccelerateInterpolator | 該插值器的變化率在開始時(shí)較為緩慢兴垦,然后會(huì)加快徙赢。 |
AnticipateInterpolator | 該插值器先反向變化,然后再急速正向變化探越。 |
AnticipateOvershootInterpolator | 該插值器先反向變化狡赐,再急速正向變化,然后超過定位值钦幔,最后返回到最終值枕屉。 |
BounceInterpolator | 該插值器的變化會(huì)跳過結(jié)尾處。 |
CycleInterpolator | 該插值器的動(dòng)畫會(huì)在指定數(shù)量的周期內(nèi)重復(fù)鲤氢。 |
DecelerateInterpolator | 該插值器的變化率開始很快搀擂,然后減速。 |
LinearInterpolator | 該插值器的變化率恒定不變卷玉。 |
OvershootInterpolator | 該插值器會(huì)急速正向變化哨颂,再超出最終值,然后返回相种。 |
TimeInterpolator | 該接口用于實(shí)現(xiàn)您自己的插值器威恼。 |
使用AnimatorSet 編排多個(gè)動(dòng)畫
在許多情況下,您需要根據(jù)一個(gè)動(dòng)畫開始或結(jié)束的時(shí)間來播放另一個(gè)動(dòng)畫蚂子。借助 Android 系統(tǒng)沃测,您可以將動(dòng)畫捆綁到一個(gè) AnimatorSet 中,以便指定是同時(shí)播放動(dòng)畫食茎、按順序播放還是在指定的延遲時(shí)間后播放蒂破。您還可以相互嵌套 AnimatorSet 對象。
以下代碼段通過以下方式播放相應(yīng)的 Animator 對象:
- 播放 bounceAnim别渔。
- 同時(shí)播放 squashAnim1附迷、squashAnim2、stretchAnim1 和 stretchAnim2哎媚。
- 播放 bounceBackAnim喇伯。
- 播放 fadeAnim。
AnimatorSet bouncer = new AnimatorSet();
bouncer.play(bounceAnim).before(squashAnim1);
bouncer.play(squashAnim1).with(squashAnim2);
bouncer.play(squashAnim1).with(stretchAnim1);
bouncer.play(squashAnim1).with(stretchAnim2);
bouncer.play(bounceBackAnim).after(stretchAnim2);
ValueAnimator fadeAnim = ObjectAnimator.ofFloat(newBall, "alpha", 1f, 0f);
fadeAnim.setDuration(250);
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.play(bouncer).before(fadeAnim);
animatorSet.start();