Android中添加動(dòng)畫

動(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)畫示例。


圖 1. 線性動(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)的距離。

圖 2. 非線性動(dòng)畫示例

我們來詳細(xì)了解一下屬性動(dòng)畫系統(tǒng)的重要組成部分將如何計(jì)算如上所示的動(dòng)畫钢悲。圖 3 描繪了主類之間是如何相互協(xié)作的点额。

圖 3. 如何計(jì)算動(dòng)畫

ValueAnimator對象跟蹤動(dòng)畫的時(shí)間,例如動(dòng)畫的已運(yùn)行時(shí)長以及正在添加動(dòng)畫效果的屬性的當(dāng)前值莺琳。

ValueAnimator 包含 TimeInterpolatorTypeEvaluator还棱;前者用于定義動(dòng)畫插值,后者用于定義如何計(jì)算正在添加動(dòng)畫效果的屬性的值惭等。例如珍手,在圖 2 中,所用的 TimeInterpolatorAccelerateDecelerateInterpolator辞做,所用的 TypeEvaluatorIntEvaluator琳要。

要開始動(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 對象:

  1. 播放 bounceAnim别渔。
  2. 同時(shí)播放 squashAnim1附迷、squashAnim2、stretchAnim1 和 stretchAnim2哎媚。
  3. 播放 bounceBackAnim喇伯。
  4. 播放 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();
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末拨与,一起剝皮案震驚了整個(gè)濱河市稻据,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌买喧,老刑警劉巖捻悯,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件匆赃,死亡現(xiàn)場離奇詭異,居然都是意外死亡今缚,警方通過查閱死者的電腦和手機(jī)算柳,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來姓言,“玉大人瞬项,你說我怎么就攤上這事『渭裕” “怎么了囱淋?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長兽泣。 經(jīng)常有香客問我绎橘,道長,這世上最難降的妖魔是什么唠倦? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任称鳞,我火速辦了婚禮,結(jié)果婚禮上稠鼻,老公的妹妹穿的比我還像新娘冈止。我一直安慰自己,他們只是感情好候齿,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布熙暴。 她就那樣靜靜地躺著,像睡著了一般慌盯。 火紅的嫁衣襯著肌膚如雪御铃。 梳的紋絲不亂的頭發(fā)上福扬,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼寇壳。 笑死糕簿,一個(gè)胖子當(dāng)著我的面吹牛特占,可吹牛的內(nèi)容都是我干的掸刊。 我是一名探鬼主播,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼禁漓,長吁一口氣:“原來是場噩夢啊……” “哼跟衅!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起播歼,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤伶跷,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體撩穿,經(jīng)...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡磷支,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了食寡。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,785評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡廓潜,死狀恐怖抵皱,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情辩蛋,我是刑警寧澤呻畸,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站悼院,受9級(jí)特大地震影響伤为,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜据途,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一绞愚、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧颖医,春花似錦位衩、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至佛致,卻和暖如春贮缕,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背俺榆。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工感昼, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人肋演。 一個(gè)月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓抑诸,卻偏偏與公主長得像,于是被迫代替她去往敵國和親爹殊。 傳聞我的和親對象是個(gè)殘疾皇子蜕乡,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評論 2 354

推薦閱讀更多精彩內(nèi)容