在Android中的動(dòng)畫(huà)主要有四種形式
1.Tween Aniamtion(變換動(dòng)畫(huà))
2.Property Animation(屬性動(dòng)畫(huà))
3.Layout Animation(布局動(dòng)畫(huà))
4.Frame Animation(逐幀動(dòng)畫(huà))
在我們的應(yīng)用中適當(dāng)?shù)厥褂脛?dòng)畫(huà)盒粮,可以讓我們的應(yīng)用更加美觀械荷、柔和搪花,對(duì)用戶來(lái)說(shuō)也會(huì)更加友好萍程。
Tween Aniamtion
Tween Animation分為四種:
Alpha:漸變透明度動(dòng)畫(huà)
Scale:漸變尺寸縮放動(dòng)畫(huà)
Translate:位置移動(dòng)變換動(dòng)畫(huà)
Rotate:旋轉(zhuǎn)動(dòng)畫(huà)
共同屬性:
(1)duration:動(dòng)畫(huà)持續(xù)時(shí)間。單位:毫秒
(2)reaptCount:動(dòng)畫(huà)重復(fù)次數(shù)
(3)reaptMode:動(dòng)畫(huà)重復(fù)模式(值:倒序重復(fù) REVERSE厨喂,順序重復(fù) RESTART)
(4)startOffset:動(dòng)畫(huà)之間的時(shí)間間隔
(5)fillAfter:設(shè)置為true吴超,表示動(dòng)畫(huà)轉(zhuǎn)化效果在動(dòng)畫(huà)結(jié)束后被應(yīng)用
(6)fillBefore:設(shè)置為true,表示動(dòng)畫(huà)轉(zhuǎn)化效果在動(dòng)畫(huà)開(kāi)始前被應(yīng)用
(7)interprolator:動(dòng)畫(huà)插入器(加速剂娄、減速插入器)
以上的共同屬性都可以通過(guò)set方式進(jìn)行設(shè)置蠢涝。
下面對(duì)這四種動(dòng)畫(huà)類型一一介紹
我們首先初始化一個(gè)View,以便下面演示
ImageView img = new ImageView(this)
1.Alpha
對(duì)view的透明度進(jìn)行設(shè)置的取值范圍是0.0~1.0
0.0表示完全透明 1.0表示完全不透明
Java Code:
AlphaAnimation alpha = new AlphaAnimation(0F,1F);
該構(gòu)造方法中的第一個(gè)參數(shù)是初始透明度,第二個(gè)參數(shù)是最終透明度阅懦。
alpha.setDuration(1000)//設(shè)置持續(xù)時(shí)間
最后使用Vew的startAnimation()
方法開(kāi)始執(zhí)行動(dòng)畫(huà)
img.startAnimation(alpha)//開(kāi)始執(zhí)行動(dòng)畫(huà)
XML配置文件
在xml中編寫(xiě)動(dòng)畫(huà)代碼和二,需要在工程中的res目錄下添加anim目錄,然后在該目錄中新建一個(gè)xml文件耳胎,然后如下編寫(xiě):
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
android:fromAlpha="0"
android:toAlpha="1"
android:duration="1000">
</alpha>
然后在Java Code中使用AnimationUtils類的loadAnimation(Context context, int id)
將xml中的動(dòng)畫(huà)文件加載進(jìn)來(lái)惯吕。同樣對(duì)于View使用startAnimation()
方法即可
2.Scale
對(duì)View縮放的取值范圍是從0~
0表示消失 1表示不縮放 >1表示放大
Java Code
ScaleAnimation有三個(gè)構(gòu)造方法:
public ScaleAnimation(float fromX, float toX, float fromY, float toY)//前兩個(gè)參數(shù)是ViewX方向的縮放,后兩個(gè)參數(shù)是ViewY方向的縮放
public ScaleAnimation(float fromX, float toX, float fromY, float toY,float pivotX, float pivotY)//前四個(gè)參數(shù)和第一個(gè)構(gòu)造方法一樣怕午,最后兩個(gè)參數(shù)是縮放的中心點(diǎn)
public ScaleAnimation(float fromX, float toX, float fromY, float toY,int pivotXType, float pivotXValue, int pivotYType, float pivotYValue)
對(duì)于第三個(gè)構(gòu)造方法中前四個(gè)參數(shù)和第一個(gè)構(gòu)造方法一樣废登,后面四個(gè)參數(shù):pivotXType與pivotYType指縮放中心點(diǎn)的類型,其值在Animation類中有定義:
RELATIVE_TO_SELF//指相對(duì)自身設(shè)置縮放中心
RELATIVE_TO_PARENT//指相對(duì)于view的父View設(shè)置縮放中心
ABSOLUTE//絕對(duì)的
最后的兩個(gè)參數(shù)需使用百分比的方式設(shè)置縮放中心郁惜,即值為0~1F堡距。
XML配置文件
<scale xmlns:android="http://schemas.android.com/apk/res/android"
android:fromXScale="0"
android:toXScale="1"
android:fromYScale="0"
android:toYScale="1"
android:pivotX="50%"
android:pivotY="50%"
android:duration="1000">
</scale>
使用XML文件配置動(dòng)畫(huà)時(shí),pivotX與pivotY既可以使用百分比方式扳炬,也可以使用dp方式
3.Translate
Java Code
Translate有兩個(gè)構(gòu)造方法:
public TranslateAnimation(float fromXDelta, float toXDelta, float fromYDelta, float toYDelta)//很容易理解吏颖,即X方向的移動(dòng)距離,Y方向的移動(dòng)距離
public TranslateAnimation(int fromXType, float fromXValue, int toXType, float toXValue,
int fromYType, float fromYValue, int toYType, float toYValue)
第二個(gè)構(gòu)造方法中的fromXType與fromYType與ScaleAnimation中的pivotXType的值是一樣的,默認(rèn)為相對(duì)自身的當(dāng)前位置恨樟,其他參數(shù)與第一個(gè)構(gòu)造方法的參數(shù)含義一樣
XML配置文件
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromXDelta="0"
android:toXDelta="100"
android:fromYDelta="0"
android:toYDelta="100"
android:duration="1000">
</translate>
比較簡(jiǎn)單半醉,就不做詳細(xì)介紹了。
4.Rotate
Java Code
RotateAnimation也有三個(gè)常用的構(gòu)造方法:
public RotateAnimation(float fromDegrees, float toDegrees)//初始(from)的角度劝术,結(jié)束時(shí)(to)的角度
public RotateAnimation(float fromDegrees, float toDegrees, float pivotX, float pivotY)
public RotateAnimation(float fromDegrees, float toDegrees, int pivotXType, float pivotXValue,int pivotYType, float pivotYValue)
后面兩個(gè)構(gòu)造方法的參數(shù)其實(shí)和上面介紹的Scale是一樣缩多,就不做介紹了
XML配置文件
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:fromDegrees="0"
android:pivotX="50%"
android:pivotY="50%"
android:toDegrees="360">
</rotate>
5.Animation中的interprolator
Animation中的interprolator最底層的接口是
public interface TimeInterpolator
他的子類有:
AccelerateInterpolator
加速插值器(動(dòng)畫(huà)速率開(kāi)始很慢呆奕,然后逐漸加速)
DecelerateInterpolator
減速插值器(動(dòng)畫(huà)速率開(kāi)始很快,然后逐漸減速)
AccelerateDecelerateInterpolator
加速減速插值器(動(dòng)畫(huà)速率開(kāi)始慢然后塊)
LinearInterpolator
線性插值器(最簡(jiǎn)單的插值器衬吆,即使動(dòng)畫(huà)勻速運(yùn)動(dòng))
BounceInterpolator
彈跳插值器(在動(dòng)畫(huà)結(jié)束時(shí)使View呈彈跳狀態(tài))
AnticipateInterpolator
回蕩秋千插值器(開(kāi)始向后蕩梁钾,然后向前蕩的插值器)
CycleInterpolator
正弦周期變化插值器(動(dòng)畫(huà)循環(huán)播放特定的次數(shù),速率改變沿著正弦曲線)
OvershootInterpolator
向前甩一定值后再回到原來(lái)位置
AnticipateOvershootInterpolator
開(kāi)始的時(shí)候向后然后向前甩一定值后返回最后的值
Property Animation
屬性動(dòng)畫(huà)實(shí)在API3.0之后出現(xiàn)的逊抡。屬性動(dòng)畫(huà)相對(duì)于Tween傳統(tǒng)動(dòng)畫(huà)具有一定的優(yōu)越性姆泻,因?yàn)閭鹘y(tǒng)動(dòng)畫(huà)是不斷調(diào)用onDraw()方法去重繪界面來(lái)實(shí)現(xiàn)動(dòng)畫(huà)效果,這在一定程度上必定會(huì)加大CPU負(fù)擔(dān)冒嫡,從而帶來(lái)性能問(wèn)題拇勃,并且傳統(tǒng)動(dòng)畫(huà)只是重繪了界面,改變了View的顯示位置孝凌,但是對(duì)用戶的onClick等響應(yīng)事件并沒(méi)有發(fā)生相應(yīng)的變化方咆,所以傳統(tǒng)動(dòng)畫(huà)并不適于那些具有交互的動(dòng)畫(huà)效果。而屬性動(dòng)畫(huà)是改變View的屬性值蟀架,真真正正改變了一個(gè)View瓣赂,因此屬性動(dòng)畫(huà)大大改變了傳統(tǒng)動(dòng)畫(huà)的局限性。
ObjectAnimator
ObjectAnimator是屬性動(dòng)畫(huà)中比較簡(jiǎn)單基礎(chǔ)的類片拍,我們可以使用以下方法為一個(gè)View添加動(dòng)畫(huà)效果煌集。
public static ObjectAnimator ofFloat(Object target, String propertyName, float... values)
第一個(gè)參數(shù)即要添加動(dòng)畫(huà)效果的View
第二個(gè)參數(shù)時(shí)屬性名稱。其實(shí)只要一個(gè)View的API中為某個(gè)屬性設(shè)置setter/getter方法穆碎,我們就可以為它添加屬性動(dòng)畫(huà)牙勘,這個(gè)屬性名稱可以為"rotation"职恳、"translateX"所禀、"translateY"、"X"放钦、"Y"等View屬性色徘。
第三個(gè)參數(shù)是一個(gè)可變參數(shù),即我們需要設(shè)置的動(dòng)畫(huà)值操禀。例如:
ObjectAnimator.ofFloat(img, "translateX", 0F, 100F);//X方向的偏移
ObjectAnimator.ofFloat(img, "translateY", 0F, 100F);//Y方向的偏移
多重動(dòng)畫(huà)的添加褂策,我們可以使用如下方式
方式一:
ObjectAnimator.ofFloat(img, "translateX", 0F, 100F).setDuration(1000).start();
ObjectAnimator.ofFloat(img, "translateY", 0F, 100F).setDuration(1000).start();
這種方式并不是先執(zhí)行“translateX”動(dòng)畫(huà),再執(zhí)行“translateY”動(dòng)畫(huà)颓屑,而是同時(shí)執(zhí)行
方式二:
PropertyValuesHolder p1 = PropertyValuesHolder.ofFloat("rotation",0F,360F);
PropertyValuesHolder p2 = PropertyValuesHolder.ofFloat("translateX",0F,100F);
ObjectAnimator.ofPropertyValuesHolder(img,p1,p2).setDuration(1000).start();
方式三:
Animator anim1 = ObjectAnimator.ofFloat(img, "translateX", 0F, 100F);
Animator anim2 = ObjectAnimator.ofFloat(img, "translateY", 0F, 100F);
AnimatorSet set = new AnimatorSet();
set.setDuration(1000);
set.playTogether(anim1,anim2);
set.start();
在AnimatorSet類中斤寂,有很多方法方便我們控制動(dòng)畫(huà)的執(zhí)行流程
public void playSequentially(Animator... items)//順序執(zhí)行items
public Builder with(Animator anim)//與某個(gè)動(dòng)畫(huà)同時(shí)執(zhí)行
public Builder before(Animator anim)//在某個(gè)動(dòng)畫(huà)執(zhí)行之前執(zhí)行anim
public Builder after(Animator anim)//在某個(gè)動(dòng)畫(huà)執(zhí)行后執(zhí)行anim
動(dòng)畫(huà)監(jiān)聽(tīng)事件AnimatorListener
ObjectAnimator anim = ObjectAnimator.ofFloat(root, "translateX", 0F, 100F);
anim.addListener(new Animator.AnimatorListener(){
@Override
public void onAnimationStart(Animator animation){}//動(dòng)畫(huà)開(kāi)始時(shí)執(zhí)行
@Override
public void onAnimationEnd(Animator animation){}//動(dòng)畫(huà)結(jié)束后執(zhí)行
@Override
public void onAnimationCancel(Animator animation){}//動(dòng)畫(huà)被取消掉時(shí)執(zhí)行
@Override
public void onAnimationRepeat(Animator animation){}//動(dòng)畫(huà)重復(fù)時(shí)執(zhí)行
});
當(dāng)然有時(shí)候我們并不需要監(jiān)聽(tīng)動(dòng)畫(huà)的這么多事件,那么我們可以使用AnimatorListenerAdapter這個(gè)抽象類揪惦,去重寫(xiě)我們需要監(jiān)聽(tīng)的事件即可遍搞。
anim1.addListener(new AnimatorListenerAdapter(){
@Override
public void onAnimationEnd(Animator animation){
super.onAnimationEnd(animation);
}
});
Layout Animation
所謂布局動(dòng)畫(huà)即添加到布局的動(dòng)畫(huà)效果,并且動(dòng)畫(huà)效果會(huì)影響到布局的子對(duì)象器腋。
為布局添加動(dòng)畫(huà)需要使用到LayoutAnimationController這個(gè)類溪猿,該類有兩個(gè)常用構(gòu)造方法
public LayoutAnimationController(Animation animation)
public LayoutAnimationController(Animation animation, float delay)
這兩個(gè)構(gòu)造比較容易理解钩杰,往構(gòu)造方法中傳遞一個(gè)Animation參數(shù)即可。第二個(gè)構(gòu)造方法中的delay(延遲)指子對(duì)象出現(xiàn)的先后延遲時(shí)間诊县,即第一個(gè)View子對(duì)象開(kāi)始出現(xiàn)后delay秒讲弄,第二個(gè)View子對(duì)象出現(xiàn)。
新建好LayoutAnimationController對(duì)象之后依痊,使用
view.setLayoutAnimation(LayoutAnimationController controller)
這樣我們就為布局添加好了動(dòng)畫(huà)效果避除。
LayoutAnimationController中有這樣一個(gè)方法setOrder(int order),該方法指定布局中子View出現(xiàn)的先后順序胸嘁,API為我們制定了三個(gè)值驹饺,在LayoutAnimationController類中
ORDER_NORMAL//順序
ORDER_REVERSE//倒序
ORDER_RANDOM//隨機(jī)
為布局添加布局改變動(dòng)畫(huà)
在Layout的XML配置文件中使用
android:animateLayoutChanges=["true"|"false"]
這樣就會(huì)為我們的布局添加一個(gè)系統(tǒng)默認(rèn)的布局改變動(dòng)畫(huà)效果。
當(dāng)然我們也可以自定義這個(gè)動(dòng)畫(huà)效果
使用view.setLayoutTransition(LayoutTransition transition)方法即為布局添加了一個(gè)默認(rèn)的布局改變動(dòng)畫(huà)缴渊,如果想改變這個(gè)動(dòng)畫(huà)赏壹,需要使用到
public void setAnimator(int transitionType, Animator animator)
這個(gè)方法,第一個(gè)參數(shù)指布局改變的類型衔沼,在LayoutTransition 類中API為我們提供了5個(gè)值
CHANGE_APPEARING//由于主容器新增加了一個(gè)View蝌借,而導(dǎo)致原來(lái)的View位置發(fā)生改變時(shí)觸發(fā)的動(dòng)畫(huà)
CHANGE_DISAPPEARING//由于主容器移除了一個(gè)View,而導(dǎo)致原來(lái)的View位置發(fā)生改變時(shí)觸發(fā)的動(dòng)畫(huà)
APPEARING//View顯示時(shí)的動(dòng)畫(huà)
DISAPPEARING//View消失時(shí)的動(dòng)畫(huà)
CHANGING//包含上面所有的情況
XML配置文件
我們也可以在XML文件中為布局設(shè)置布局動(dòng)畫(huà)
首先使用XML創(chuàng)建一個(gè)Tween Animation
然后使用XML通過(guò)以下語(yǔ)法創(chuàng)建一個(gè)布局動(dòng)畫(huà)
<layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"
android:animation="@[package:]anim/anim_resource_name"
android:delay="0.5">
</layoutAnimation>
根節(jié)點(diǎn)必須是layoutAnimation指蚁,android:animation指定義的Tween Animation
最后在layout布局中為布局使用android:layoutAnimation="@[package:]anim/anim_resource_name"
將我們編寫(xiě)的layoutAnimation文件的文件名傳遞進(jìn)去即可菩佑。
Frame Animation
這種類型的動(dòng)畫(huà),在官方文檔中是這樣介紹的:
Frame動(dòng)畫(huà)是一系列圖片按照一定的順序展示的過(guò)程凝化,和放電影的機(jī)制很相似稍坯,我們稱之為逐幀動(dòng)畫(huà)。Frame動(dòng)畫(huà)既可以在XML文件中定義搓劫,也可以完全編碼實(shí)現(xiàn)瞧哟。
XML配置文件
在XML中進(jìn)行定義時(shí),文件既可以放在anim目錄中也可以放在drawable文件中枪向。語(yǔ)法如下:
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot=["true" | "false"] >
<item
android:drawable="@[package:]drawable/drawable_resource_name"
android:duration="integer" />
</animation-list>
animation-list作為根節(jié)點(diǎn)是必須的
android:oneshot若設(shè)值為true表示動(dòng)畫(huà)執(zhí)行一次勤揩,若設(shè)值為false表示動(dòng)畫(huà)會(huì)重復(fù)執(zhí)行。
每一個(gè)<item>元素表示一幀動(dòng)畫(huà)秘蛔,android:drawable表示一幀所對(duì)應(yīng)的圖片陨亡,android:duration表示該幀所執(zhí)行的時(shí)間。
Java Code
若以純編碼實(shí)現(xiàn)Frame動(dòng)畫(huà)需要用到AnimationDrawable類深员,該類是Drawable的子類负蠕。
在Java代碼中我們可以使用setBackgroundResource()方法將我們XML中定義的Frame動(dòng)畫(huà)設(shè)置到ImageView上
image.setBackgroundResource(R.anim.frame);
AnimationDrawable anim = (AnimationDrawable) image.getBackground();
anim.start();
如果想要停止掉動(dòng)畫(huà),只需調(diào)用anim.stop()方法即可倦畅。
還可以通過(guò)以下方式定義一個(gè)Frame動(dòng)畫(huà)
AnimationDrawable frame = new AnimationDrawable();
for(int i = 0; i< 4; i++){
int id = getResources().getIdentifier("f"+i,"drawable",getPackageName());
Drawable drawable = getResources().getDrawable(id);
frame.addFrame(drawable,300);
}
frame.setOneShot(true);
img.setBackgroundDrawable(frame);
frame.start();
注意:對(duì)于AnimationDrawable不要在Activity的onCreate()方法中去掉用start()方法遮糖,因?yàn)榇藭r(shí)窗口對(duì)象Window還沒(méi)有初始化,AnimationDrawable不能被追加到Window中的視圖對(duì)象中滔迈,所以并沒(méi)有效果止吁。解決辦法可以是將animation的start放在一個(gè)按鈕的點(diǎn)擊事件或其他響應(yīng)事件中被辑,也可以在onWindowFocusChanged方法中開(kāi)始執(zhí)行動(dòng)畫(huà),onWindowFocusChanged方法會(huì)在窗口初始化完成后被執(zhí)行敬惦,在onCreate()方法之后執(zhí)行盼理。