一直以來各種動(dòng)畫效果也只是零碎地在需要用到的時(shí)候復(fù)制粘貼祝闻,或者直接自己Draw一遍占卧,并且記下一些零碎的代碼段。然而最近比賽項(xiàng)目又碰到了需要各種動(dòng)畫過場(chǎng)的情況联喘,想想這問題也是積攢已久了华蜒,于是準(zhǔn)備認(rèn)真的學(xué)習(xí)一下。
? 首先豁遭,Android里的動(dòng)畫分為三種:PropertyAnimation(屬性動(dòng)畫)叭喜、ViewAnimation(視圖動(dòng)畫)和DrawableAnimation(幀動(dòng)畫,By the way蓖谢,官網(wǎng)中翻是可繪制動(dòng)畫捂蕴,感覺就很不對(duì)勁 -_-)。其中屬性動(dòng)畫在API 11之后加入闪幽,它可以對(duì)所有對(duì)象(包括未渲染到屏幕的對(duì)象)添加動(dòng)畫效果啥辨,拓展性強(qiáng)且特點(diǎn)多樣,是官方推薦的動(dòng)畫實(shí)現(xiàn)手段盯腌;視圖動(dòng)畫則是比較老的動(dòng)畫實(shí)現(xiàn)手段溉知,其僅對(duì)View起效,并且只有視覺上的變化,而不實(shí)際改變View的位置或其他真實(shí)屬性级乍;可繪制動(dòng)畫則適用于借助Drawable資源實(shí)現(xiàn)的情景舌劳,通過切換幀實(shí)現(xiàn)動(dòng)畫效果,比如常見的進(jìn)度條旋轉(zhuǎn)與游戲中人物走動(dòng)效果等卡者。下面依次說一下各個(gè)動(dòng)畫的用法蒿囤。
視圖動(dòng)畫
? 首先講講ViewAnimation,為什么不是PropertyAnimation崇决?大概是因?yàn)樗奈臋n比較短.(PropertyAnimation:明明是我先材诽,出現(xiàn)在正文也好,官方推薦也好...)恒傻。記得當(dāng)年年輕的我某一日終于忍受不了各種View硬生生直挺挺地在面前排布時(shí)脸侥,怒而百度,第一個(gè)搜出來的教程就是關(guān)于它的盈厘,然后我就實(shí)現(xiàn)了Coding以來第一個(gè)動(dòng)畫:一個(gè)很蠢的點(diǎn)擊按鈕旋轉(zhuǎn)滾動(dòng)拉出一個(gè)EditText的動(dòng)畫睁枕。ViewAnimation實(shí)際上是為了在View上實(shí)現(xiàn)TweenedAnimation,即補(bǔ)間動(dòng)畫(這個(gè)名詞在各種教程技術(shù)文里出現(xiàn)的頻率明顯也更高)沸手。它的實(shí)現(xiàn)效果就是簡(jiǎn)單地設(shè)置View進(jìn)行自定義起始點(diǎn)和結(jié)束點(diǎn)的平移外遇、旋轉(zhuǎn)、大小和透明度變換等等契吉,能夠用XML與Java代碼兩種方式實(shí)現(xiàn)跳仿,官方推薦是用XML文件(位于res/anim下)實(shí)現(xiàn),這樣會(huì)使代碼結(jié)構(gòu)看起來更清晰捐晶。下面是XML代碼的各種屬性和格式:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@[package:]anim/interpolator_resource"http://插值器類型菲语,可以設(shè)置在單獨(dú)的動(dòng)畫效果中
android:shareInterpolator=["true" | "false"] >
<alpha//設(shè)置不透明度,值為0f-1.0f
android:fromAlpha="float"
android:toAlpha="float" />
<scale//設(shè)置大小
//縮放比例惑灵,1.0f為無變化
android:fromXScale="float"
android:toXScale="float"
android:fromYScale="float"
android:toYScale="float"
//縮放中心
android:pivotX="float"
android:pivotY="float" />
<translate//設(shè)置平移
//以下值的表示規(guī)則為:普通float無后綴數(shù)字山上,如“50”,表示絕對(duì)偏移值英支;-100 - 100以“%”為后綴的值佩憾,如“50%”,表示相對(duì)自身位置的偏移值干花;-100 - 100以“%p”為后綴值妄帘,如“50%p”,表示相對(duì)父布局的偏移值把敢。
android:fromXDelta="float"
android:toXDelta="float"
android:fromYDelta="float"
android:toYDelta="float" />
<rotate//設(shè)置旋轉(zhuǎn)
//旋轉(zhuǎn)角度,單位為度谅辣,正方向?yàn)轫槙r(shí)針
android:fromDegrees="float"
android:toDegrees="float"
//旋轉(zhuǎn)中心修赞,與上面偏移值的表示規(guī)則相同,分別以無后綴、“%”與“%p”分別表示其與View邊緣(左和上)的絕對(duì)值柏副,與View邊緣的相對(duì)百分比(50%勾邦,50%則為正中心),與父布局邊緣的相對(duì)百分比割择。
android:pivotX="float"
android:pivotY="float" />
<set>
...
</set>
</set>
另外它們都有繼承自Animation的通用屬性:
屬性名 | 說明 | 參數(shù)類型 |
---|---|---|
android:detachWallpaper | 窗口動(dòng)畫的特殊選項(xiàng)眷篇,當(dāng)窗口處于壁紙之上時(shí),選擇是否讓壁紙與其一起運(yùn)動(dòng) | boolean |
android:duration | 動(dòng)畫的執(zhí)行時(shí)間荔泳,以毫秒為單位蕉饼,默認(rèn)為300ms | integer |
android:fillAfter | 為true時(shí),動(dòng)畫變換效果將保持玛歌。(僅在set中設(shè)置有效) | boolean |
android:fillBefore | 為true時(shí)昧港,動(dòng)畫運(yùn)行結(jié)束后停留在第一幀。默認(rèn)為true支子。 | boolean |
android:fillEnabled | 設(shè)為true時(shí) fiilBefore才有效创肥,為false且動(dòng)畫未設(shè)置給View時(shí),讓fillAfter為true | boolean |
android:interpolator | 設(shè)置相應(yīng)插值器值朋。 | refrence |
android:repeatCount | 設(shè)置動(dòng)畫重復(fù)次數(shù) | integer |
android:repeatMode | 動(dòng)畫播完一遍再重復(fù)時(shí)的行為模式叹侄,有restart和reverse兩種模式。 | string |
android:startOffset | 動(dòng)畫開始前的延遲時(shí)間昨登,以毫秒為單位淆储。 | integer |
android:zAdjustment | 允許調(diào)整在動(dòng)畫持續(xù)時(shí)間內(nèi)動(dòng)畫的內(nèi)容的Z排序步藕。有bottom(ffffff)、normal(0)與top(1)三種模式,默認(rèn)為normal(保持現(xiàn)有順序)淤翔。 | integer |
關(guān)于上面的interpolator,有如下系統(tǒng)默認(rèn)調(diào)用:
名稱 | 資源ID | 說明 |
---|---|---|
AccelerateDecelerateInterpolator | @android:anim/accelerate_decelerate_interpolator | 開始和結(jié)束較慢中間加快饶唤。 |
AccelerateInterpolator | @android:anim/accelerate_interpolator | 開始較慢肄程,之后加速。 |
AnticipateInterpolator | @android:anim/anticipate_interpolator | 先減速再加速得湘。 |
AnticipateOvershootInterpolator | @android:anim/anticipate_overshoot_interpolator | 先減速再加速直致越界杖玲,最后回到原速。 |
BounceInterpolator | @android:anim/bounce_interpolator | 上下起伏到后面趨于平坦淘正。 |
CycleInterpolator | @android:anim/cycle_interpolator | 重復(fù)動(dòng)畫指定的循環(huán)次數(shù)摆马。 變化率遵循正弦曲線。(也就是有正有負(fù)鸿吆,可以制造回彈效果) |
DecelerateInterpolator | @android:anim/decelerate_interpolator | 減速變化 |
LinearInterpolator | @android:anim/linear_interpolator | 線性變化 |
OvershootInterpolator | @android:anim/overshoot_interpolator | 減速增長(zhǎng)然后越界囤采,回歸原點(diǎn)。 |
上面的插值變化實(shí)際表示各種速度變化曲線惩淳,可以參考blog中的圖參考圖例
在寫好動(dòng)畫相關(guān)函數(shù)后可以用Java代碼調(diào)用:
Animation anim = AnimationUtils.loadAnimate(context,R.anim.demo);
//方式一
view.startAnimation(anim);//立即開始動(dòng)畫蕉毯,考慮上面的startOffset屬性
//方式二
anim.setStartTime(time)//設(shè)置動(dòng)畫開始時(shí)間乓搬,參數(shù)是格林威治時(shí)間至今的毫秒數(shù)
view.setAnimation(anim);//設(shè)置動(dòng)畫,當(dāng)其動(dòng)畫時(shí)間到達(dá)時(shí)則自然開始動(dòng)畫代虾。
另外进肯,需要注意的地方有:一、set內(nèi)的所有動(dòng)畫默認(rèn)都是同時(shí)運(yùn)行的棉磨,所以當(dāng)需要?jiǎng)赢嬘邢群箜樞驎r(shí)需要用startOffset來進(jìn)行延遲播放江掩。二、位移或者放大類動(dòng)畫并不會(huì)拓展View本身的空間乘瓤,當(dāng)其越界時(shí)环形,便不會(huì)顯示在界面上。三馅扣、ViewAnimation并不會(huì)改變View的真實(shí)屬性斟赚,當(dāng)其由于動(dòng)畫效果不處于本身的位置時(shí),其事實(shí)上的點(diǎn)擊區(qū)域還是在原地差油。(所以在知道屬性動(dòng)畫之前拗军,我一直都是用兩個(gè)不同時(shí)出現(xiàn)的按鈕實(shí)現(xiàn)的一開始提到的那個(gè)滾動(dòng)出EditText的效果,真的很蠢蓄喇。发侵。)
關(guān)于屬性動(dòng)畫
? 由于視圖動(dòng)畫的純“花架子”式動(dòng)畫效果,在更多需要和動(dòng)畫界面交互的場(chǎng)景中妆偏,屬性動(dòng)畫后來的上位也就不難理解了刃鳄。它的構(gòu)成部分主要有這么幾項(xiàng):ValueAnimator、 TimeInterpolator和TypeEvaluator钱骂,下面先進(jìn)行一下概述叔锐。
? ValueAnimator是整個(gè)屬性動(dòng)畫系統(tǒng)的核心基類,其中包含了動(dòng)畫的起止時(shí)間见秽,屬性變化規(guī)律和監(jiān)聽等功能愉烙,負(fù)責(zé)維護(hù)整個(gè)動(dòng)畫的運(yùn)行流程,其下子類ObjectAnimator是最常用到的屬性動(dòng)畫實(shí)現(xiàn)類解取,可以為任意對(duì)象加載動(dòng)畫效果步责,另外還有AnimatorSet,其類似XML文件內(nèi)的<set>標(biāo)簽禀苦,表示一組動(dòng)畫蔓肯。
? TimeInterpolator和TypeEvaluator事實(shí)上也不是什么新東西了,在ViewAnimation中也有相同的機(jī)制振乏,它們的運(yùn)行機(jī)制簡(jiǎn)單來說是這樣的:當(dāng)Animator設(shè)定了動(dòng)畫的起止時(shí)間并執(zhí)行start()之后蔗包,之后動(dòng)畫的每一幀都會(huì)根據(jù)開始時(shí)間與當(dāng)前時(shí)間的差與總時(shí)間的比值通過TimeInterpolator得到相應(yīng)的0-1.0間的值,然后TypeEvaluator得到這個(gè)值并由此估算出此時(shí)對(duì)象應(yīng)具有的屬性慧邮,并更新其屬性值调限,如此循環(huán)直至動(dòng)畫結(jié)束邻储。所以這一對(duì)其實(shí)就是控制動(dòng)畫播放速度(視覺上的,總時(shí)間是一定的)的工具旧噪。
接下來就是各種例子嘍,首先是ValueAnimator:
它的初始化方法有幾種脓匿,如下:
ValueAnimator animator = ValueAnimator.ofInt(startValue,endValue);
ValueAnimator animator = ValueAnimator.ofFloat(startValue,endValue);
ValueAnimator animator = ValueAnimator.ofArgb(startValue,endValue);//必須為8位ARGB值淘钟,且必須為兩個(gè)值
ValueAnimator animator = ValueAnimator.ofObject(evaluator,startValue,endValue);//這里的兩個(gè)value都是Object類型的。
Keyframe kf0 = Keyframe.ofFloat(time1, value1);//關(guān)鍵幀陪毡,記錄了在指定的time時(shí)其應(yīng)有的value米母,可以定義自己的Interceptor
Keyframe kf1 = Keyframe.ofFloat(time2, value2);
Keyframe kf2 = Keyframe.ofFloat(time3, value3);
PropertyValuesHolder pvhRotation = PropertyValuesHolder.ofKeyframe("rotation", kf0, kf1, kf2);
//"rotation"在ValueAnimator中僅僅是一個(gè)屬性的名字,只在在getAnimationValue(name)時(shí)可能會(huì)使用到毡琉,但在ObjectAnimator中就代表目標(biāo)對(duì)象的屬性
ValueAnimator rotationAnim = ValueAnimator.ofPropertyValuesHolder(pvhRotation)
//以上所有startValue 和 endValue都是可變參數(shù)铁瞒,只填一個(gè)的話會(huì)默認(rèn)從0開始,然后將填入的值為終點(diǎn)值桅滋,當(dāng)然填多個(gè)的話也沒有任何問題慧耍,甚至可以填入一串值實(shí)現(xiàn)來回變化屬性的效果
//ofInt,ofFloat 和ofArgb只是決定了TimeInterpolator計(jì)算得到的參數(shù)類型丐谋,并不影響最終結(jié)果芍碧,影響結(jié)果的永遠(yuǎn)是Evaluator
然而ValueAnimator并沒有預(yù)設(shè)的屬性動(dòng)畫效果,官網(wǎng)上給的例子是通過addUpdateListener
監(jiān)聽來自己更改View屬性的(當(dāng)然所有對(duì)象都一樣号俐,反正都是自定義)泌豆,下面是一個(gè)比較完整的一個(gè)例子:
ValueAnimator animator = ValueAnimator.ofObject(new TypeEvaluator() {
@Override
public Object evaluate(float fraction, Object startValue, Object endValue) {
return fraction*(int)endValue; //這里的算法可以隨便定義,甚至可以完全不管 TimeInterpolator傳來的fraction數(shù)值吏饿,返回值就是getAnimatedValue能拿到的值踪危。
}
},0, 100);
animator.setDuration(1000);
animator.setInterpolator(new CycleInterpolator(5));//隨便設(shè)置了一個(gè)插值器,上面有說明
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
//注意猪落,動(dòng)畫的每一幀耗費(fèi)的時(shí)間是不確定的贞远,所以這里得到的值在線性插值器條件下也只是近似線性
view.setTranslationX((float)animation.getAnimatedValue());
}
});
animator.start();//即時(shí)開始動(dòng)畫,也可以用setStartDelay進(jìn)行一下延時(shí)
為了簡(jiǎn)化ValueAnimator的使用(畢竟老是得寫匿名類監(jiān)聽還是挺占地方的)许布,ObjectAnimator便站了出來兴革,它的使用如下:
ObjectAnimator animator = ObjectAnimator.ofFloat(view,"scaleX",0.1f);
animator.setDuration(1000);
animator.start();
//大部分方法繼承自ValueAnimator,就不寫了
需要注意的是蜜唾,ObjectAnimator的工廠方法第一個(gè)參數(shù)與ValueAnimator 不同杂曲,它需要傳入一個(gè)Object(可以認(rèn)為是一個(gè)Java Bean)以及其相關(guān)屬性,在之后的屬性更新操作中袁余,會(huì)通過反射調(diào)用Object的setter和getter方法來更改屬性擎勘,要求相關(guān)Object類中必須有setter和getter方法(如屬性字段size,需要在Object類中定義setSize和getSize方法颖榜,方法參數(shù)與返回值必須與傳入數(shù)據(jù)類型相同)棚饵,若無法控制Object的方法煤裙,則要做一個(gè)符合要求的包裝類。對(duì)于View噪漾,除了上面的scaleX硼砰,還有幾個(gè)常用的預(yù)定義屬性:translationX和translationY,rotation(繞中心在水平面內(nèi)順時(shí)針旋轉(zhuǎn)) rotationX(繞X軸在立體面內(nèi)旋轉(zhuǎn))和rotationY(繞Y軸在立體面內(nèi)旋轉(zhuǎn))欣硼,pivotX和pivotY(設(shè)置縮放與平移的中心题翰,默認(rèn)為View中心),alpha以及backgroundColor等View屬性诈胜,Android實(shí)際上對(duì)其也做了一層封裝豹障,即ViewPropertyAnimator類:
view.animate().scaleX(0.5f).scaleY(0.5f).duration(1000).start();//默認(rèn)以中心縮小一倍
view.animate().translationY(200).duration(1000).start();//向下移動(dòng)200px
view.animate().alpha(0f).duration(1000).start();//從當(dāng)前透明度變至完全透明
//注意,這里的所有動(dòng)畫都是有絕對(duì)的默認(rèn)中心的焦匈。而當(dāng)運(yùn)行過前面的動(dòng)畫后血公,默認(rèn)中心仍不會(huì)變。如translationY(200)后回到原位置的方式并不是translationY(-200),而是translationY(0)
關(guān)于AnimatorSet主要是幾個(gè)動(dòng)畫調(diào)度方法:
AnimatorSet set = new AnimatorSet();
set.playSequentially(anim1,anim2,anim3);//在start后順序播放參數(shù)列表內(nèi)的動(dòng)畫
set.playTogether(anim1,anim2,anim3);//在start后同時(shí)播放參數(shù)列表內(nèi)的動(dòng)畫
//AnimatorSet.Builder調(diào)用
set.play(anim1).with(anim2);//start后同時(shí)播放動(dòng)畫1和動(dòng)畫2
set.play(anim2).before(anim3);//在播放動(dòng)畫2之后播放動(dòng)畫3
set.play(anim4).after(anim3);//在播放動(dòng)畫3之后播放動(dòng)畫4
set.play(anim4).after(1000);//在start后1秒播放動(dòng)畫4
set.start();
//注意缓熟,上面的鏈?zhǔn)秸{(diào)用相鄰鏈之間是并列關(guān)系累魔,如set.play(anim1).before(anim2).before(anim3)播放順序?yàn)閯?dòng)畫1先播放,動(dòng)畫2和動(dòng)畫3同時(shí)播放
其實(shí)如果僅是同時(shí)運(yùn)行的話够滑,用上面出現(xiàn)過的PropertyValuesHolder也能實(shí)現(xiàn)與AnimatorSet相似的效果:
PropertyValuesHolder pvhX = PropertyValuesHolder.ofFloat("x", 50f);
PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat("y", 100f);
ObjectAnimator.ofPropertyValuesHolder(myView, pvhX, pvyY).start();//這里的工廠方法仍然是可變參數(shù)的方法薛夜,所以可以添加多個(gè)動(dòng)畫同時(shí)運(yùn)行
與ViewAnimation相同,PropertyAnimation也能通過XML文件定義版述,文件存放在res/animator目錄下以跟原來的animation區(qū)分梯澜,其對(duì)應(yīng)上面三個(gè)類的標(biāo)簽分別為<animator> <objectAnimator>和<set>,其相關(guān)定義如下:
<set
android:ordering=["together" | "sequentially"]> //共同運(yùn)行(默認(rèn))和順序執(zhí)行
<objectAnimator
android:propertyName="string" //屬性名,如alpha渴析,background等屬性
android:duration="int" //運(yùn)行時(shí)長(zhǎng)
android:valueFrom="float | int | color" //起始值
android:valueTo="float | int | color" //終點(diǎn)值
android:startOffset="int" //起始時(shí)間延遲
android:repeatCount="int" //重復(fù)次數(shù)晚伙,-1為無限重復(fù),0為不重復(fù)
android:repeatMode=["repeat" | "reverse"] //重復(fù)模式俭茧,順序或倒序咆疗,僅在repeatCount為正數(shù)或-1時(shí)起效
android:valueType=["intType" | "floatType"]/> //值類型,關(guān)系到后面估值器的返回值
<animator
android:duration="int"
android:valueFrom="float | int | color"
android:valueTo="float | int | color"
android:startOffset="int"
android:repeatCount="int"
android:repeatMode=["repeat" | "reverse"]
android:valueType=["intType" | "floatType"]/>
<set>
...
</set>
</set>
在定義了XML后母债,在Java代碼中調(diào)用:
//調(diào)用ValueAnimator
ValueAnimator animator = (ValueAnimator)AnimatorInflater(context,R.animator.anim);
animator.addUpdateListener(mListener);//在監(jiān)聽里更新屬性
animator.start();
//調(diào)用ObjectAnimator
ObjectAnimator animator = (ObjectAnimator)AnimatorInflater(context,R.animaror.anim);
animator.setTarget(view);//設(shè)置作用對(duì)象午磁,此時(shí)該對(duì)象必須含有propertyName屬性以及其setter getter方法
animator.start();
//調(diào)用AnimatorSet
AnimatorSet set = (AnimatorSet)AnimatorInflater(context,R.animtor.anim);
set.setTarget(view);//這里主要是set里的動(dòng)畫為ObjectAnimator的情況,事實(shí)上將ValueAnimator放在set里是沒有意義的毡们,因?yàn)閟et中沒有相關(guān)的更新回調(diào)方法迅皇,沒有辦法更新ValueAnimator指定的屬性
set.start();
至此屬性動(dòng)畫的基本使用都說完了。不過上面寫到的動(dòng)畫效果都是需要人為調(diào)用的衙熔,事實(shí)上Android還提供了一些在特定情景下自動(dòng)調(diào)用的動(dòng)畫效果登颓,這就是 以LayoutTransition表現(xiàn)的布局動(dòng)畫()。
添加布局動(dòng)畫的方式很簡(jiǎn)單红氯,只要在XML文件中的某個(gè)ViewGroup標(biāo)簽下加上一行:
android:animateLayoutChanges="true"
則當(dāng)布局發(fā)生變化(一般是add框咙、remove咕痛、setVisibility等情況下)時(shí),就會(huì)有默認(rèn)的控件fade或者上滑等效果喇嘱。在源碼中可以看到茉贡,當(dāng)這個(gè)值為true時(shí),ViewGroup便設(shè)置了一個(gè)LayoutTransition:
case R.styleable.ViewGroup_animateLayoutChanges:
boolean animateLayoutChanges = a.getBoolean(attr, false);
if (animateLayoutChanges) {
setLayoutTransition(new LayoutTransition());
}
break;
同樣地者铜,我們也可以在代碼中通過設(shè)置LayoutTransition的方式來設(shè)置布局動(dòng)畫块仆,并且LayoutTransition的動(dòng)畫效果可以自定義。從官方文檔中可以看到王暗,LayoutTransition的動(dòng)畫分為四種情景:
APPEARING -View出現(xiàn)在布局中的動(dòng)畫標(biāo)志。
CHANGE_APPEARING -由于新View出現(xiàn)在布局中而造成其他View改變的動(dòng)畫庄敛。
DISAPPEARING - View消失在布局中時(shí)的動(dòng)畫標(biāo)志俗壹。
-
CHANGE_DISAPPEARING - 由于View消失在布局中而造成其他View改變的動(dòng)畫。
?
其設(shè)置方法如下:
transition.setAnimator(LayoutTransition.APPEARING,appearingAnim);
transition.setAnimator(LayoutTransition.DISAPPEARING,disappearingAnim);
transition.setAnimator(LayoutTransition.CHANGE_APPEARING,changingAppearingAnim);
transition.setAnimator(LayoutTransition.CHANGE_DISAPPEARING,changingDisappearingAnim);
//上面的參數(shù)都是普通的ObjectAnimator或者ValueAnimator藻烤。
關(guān)于幀動(dòng)畫
相對(duì)上面兩種動(dòng)畫來說绷雏,幀動(dòng)畫真的不能再簡(jiǎn)單了。其動(dòng)畫實(shí)現(xiàn)原理不同于上面的View局部更新重繪怖亭,而是簡(jiǎn)單粗暴地一幀幀切換已有的圖片涎显,它的XML文件直接放在res/drawable文件夾下,結(jié)構(gòu)如:
<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot=["true" | "false"] > //只播放一次或者循環(huán)播放
<item
android:drawable="@[package:]drawable/drawable_resource_name" //準(zhǔn)備的圖片
android:duration="integer" /> //該幀播放時(shí)長(zhǎng)
...
</animation-list>
在Java中使用時(shí)也就幾行代碼:
ImageView iv = (ImageView) findViewById(R.id.iv);
iv.setBackgroundResource(R.drawable.anim);
animation = (AnimationDrawable) iv.getBackground();
rocketAnimation.start();
就這么簡(jiǎn)單兴猩,但是需要注意的是期吓,不能在onCreate中調(diào)用start()方法,官方解釋是此時(shí)AnimationDrawable對(duì)象還未加載到窗口上倾芝,故推薦有這個(gè)需求是通過在onWindowFocusChanged()中開始動(dòng)畫讨勤,此時(shí)表示Android已經(jīng)將焦點(diǎn)聚集在窗口上,即動(dòng)畫已經(jīng)加載完畢晨另。
最后
各種翻文檔后終于是搞定了這篇其實(shí)并沒有多高深的筆記潭千,里面有些東西被省略了,比如動(dòng)畫狀態(tài)的監(jiān)聽借尿,不過日常大概也不太會(huì)被這種看字面就能理解的東西難住刨晴。還有挺重要的一點(diǎn)是layoutAnimation和Activity Fragment等整體組件切換的動(dòng)畫,某些是5.0以后的效果路翻,以后大概會(huì)補(bǔ)上狈癞。總之以后寫些小動(dòng)畫但想不起來屬性時(shí)終于能告別百度和忍受那些糟糕的界面了茂契,開心亿驾。
如果上面的內(nèi)容有任何錯(cuò)誤或不足,歡迎各種交流指導(dǎo)账嚎,鞠躬莫瞬。
個(gè)人Github主頁(yè):Lazxy