一.View動畫
1.View動畫的種類
Android中的View動畫分為平移動畫呻拌、縮放動畫、旋轉(zhuǎn)動畫睦焕、透明度動畫和幀動畫藐握。其中幀動畫的表現(xiàn)形式和前四種的變換效果不太一樣,所以在后面會單獨(dú)來介紹垃喊,這里先來介紹前4種猾普。
2.View動畫詳解
動畫的子類:View動畫的前四種變換效果對應(yīng)著Animation的四個子類:TranslateAnimation、ScaleAnimation本谜、RotateAnimation和AlphaAnimation初家。
創(chuàng)建的方法:前4種動畫既可以通過XML定義,創(chuàng)建的位置是res/anim/filename乌助,也可以通過代碼來進(jìn)行動態(tài)的創(chuàng)建溜在,不過對于View動畫來說,還是建議采用XML來進(jìn)行定義動畫他托。要使用View動畫掖肋,首先要創(chuàng)建出動畫的XML文件,下面給出每一個標(biāo)簽里面的具體屬性:
<set>
<set>標(biāo)簽表示動畫的集合赏参,對應(yīng)著AnimationSet類志笼,它可以包含若干個動畫并且在它的內(nèi)部也可以嵌套其他動畫的集合,它的兩個屬性的含義如下:
1) android:interpolator:動畫集合所采用的插值器把篓,插值器會影響動畫的速度纫溃。該屬性可以不指定,默認(rèn)為@android:mnim/acclerate_decelerate_interpolator韧掩,即加速/減速插值器紊浩。
2) android:sharedInterpolator:表示集合中的動畫是否和集合共享一個插值器,如果集合不指定插值器疗锐,那么子動畫就要單獨(dú)指定所需的插值器或者是使用默認(rèn)值坊谁。<translate>
該標(biāo)簽表示的是平移動畫,對應(yīng)著TranslateAnimation類窒悔,它可以使一個View在水平和豎直方向完成平移的動畫效果呜袁,它的一系列屬性的含義如下:
1) android:fromXdelta:表示x的起始值,比如0简珠;
2) android:toXDelta:表示x的結(jié)束值阶界,比如100虹钮;
3) android:fromYDelta:表示y的起始值;
4) android:toYDelta:表示y的結(jié)束值膘融;<scale>
該標(biāo)簽表示縮放動畫芙粱,對應(yīng)ScaleAnimation,它可以使View具有放大或者縮小的動畫效果氧映,它的屬性如下
1) android:fromXScale:水平方向縮放的起始值春畔;
2) android:toXScale:水平方向縮放的結(jié)束值;
3) android:fromYScale:豎直方向縮放的起始值岛都;
4) android:toYScale:豎直方向縮放的結(jié)束值律姨;
5) android:pivotX:縮放軸點(diǎn)的x的坐標(biāo),軸點(diǎn)默認(rèn)是view的中心臼疫;
6) android:pivotY:縮放軸點(diǎn)的y坐標(biāo)择份;<rotate>
該標(biāo)簽表示的是旋轉(zhuǎn)動畫,對應(yīng)于RotateAnimation烫堤,它可以使View具有旋轉(zhuǎn)的的動畫效果荣赶,它的屬性如下:
1) android:fromDegrees:旋轉(zhuǎn)開始的角度;
2) android:toDegrees:旋轉(zhuǎn)結(jié)束的角度鸽斟;
3) android:pivotX:旋轉(zhuǎn)軸點(diǎn)的x的坐標(biāo)拔创;
4) android:pivotY:旋轉(zhuǎn)軸點(diǎn)的y坐標(biāo);<alpha>
該標(biāo)簽表示透明度動畫富蓄,對應(yīng)著AlphaAnimation剩燥,它可以改變View的透明度,它的屬性如下:
1) android:fromAlpha:表述透明度的起始值格粪;
2) android:toAlpha:表示透明度的結(jié)束值躏吊;其他屬性
除了上面介紹的標(biāo)簽內(nèi)的屬性氛改,還有一些公共屬性:
1) android:duration:動畫的持續(xù)時間帐萎;
2) android:fliiAfter:動畫結(jié)束后View是否停留在結(jié)束位置,true表示View停留胜卤,false表示不停留疆导;
實(shí)際操作的例子:首先我們要新建一個xml文件,如下所示:
// res/anim/animation_test.xml
...
<set xmlns:android="http://..."
android:fillAfter="true"
android:zAdjustment="normal">
<translate
android:duration="100"
android:fromXDelta="0"
android:fromYDelta="0"
android:toXDelta="100"
android:toYDelta="100"
android:interpolator="@android:anim/linear_interpolator"/>
<rotate
android:duration="400"
android:fromDegrees="0"
android:toDegrees="90"/>
</set>
我們在定義了一個平移和縮放的動畫集合葛躏,接著我們將這個動畫設(shè)置到一個按鈕上:
Button mButton = (Button)findViewById(R.id.button1);
Animation animation = AnimationUtils.loadAnimation(this,R.anim.animation_test); //給出具體的動畫位置
mButton.startAnimation(animation); //啟動動畫
3.幀動畫
概念:幀動畫是按順序播放一組預(yù)先定義好的圖片澈段,類似與電影播放。之所以說它與前四種View動畫不同舰攒,是因?yàn)橄到y(tǒng)為它單獨(dú)提供了另一個類AnimationDrawable败富。
創(chuàng)建方法:幀動畫是需要使用XML來進(jìn)行定義一個AnimationDrawable,實(shí)例如下:
// res/drawable/frame_animation.xml
...
<animation-list xmlns:android="http://..."
android:onshot="false">
<item android:drawable="圖片1"/>
<item android:drawable="圖片2"/>
<item android:drawable="圖片3"/>
/>
如果要將上述的Drawable設(shè)置到View上摩窃,則需要進(jìn)行如下操作:
Button mButton = (Button)findViewById(R.id.button1);
mButton.setBackgroundResource(R.drawable.frame_animation); //先將Drawable設(shè)置為背景
AnimationDrawable drawable = (AnimationDrawable) mButton.getBackground();
drawable.start();
二.View動畫的特殊使用場景
1.LayoutAnimation
概念:LayoutAnimation作用于ViewGroup兽叮,為ViewGroup指定一個動畫芬骄,這樣當(dāng)它的子元素出場時都會有這種效果。這種效果常常被用在ListView上鹦聪,即它每一個item都會以一定的動畫形式出現(xiàn)账阻。
使用方法:首先還是需要在XML中定義:
// res/anim/anim_layout.xml
<LayoutAnimation xmlns:android="http://..."
android:delay="0.5"
android:animationOrder="normal"
android:animation="@anim/anim_item"
/>
它的各個屬性的介紹如下:
android:delay
表示子元素開始動畫的時間延遲,例如子元素入場動畫的時間周期時300ms泽本,那么0.5就表示每個子元素都需要延遲150ms才能播放入場動畫淘太。android:animationOrder
表示子元素動畫的順序,有三種選項(xiàng):normal(順序顯示)规丽、reverse(逆向顯示)和random(隨機(jī)顯示)蒲牧。Android:animation
為子元素指定具體的入場動畫。
在XML中定義好了之后赌莺,就需要為子元素設(shè)置具體的入場動畫:
// res/anim/anim_item.xml
<set xmlns:android="http://..."
android:duration="300"
android:interpolator="@android:anim/accelerate_interpolator"
android:sharedInterpolator="true">
<alpha
android:fromAlpha="0.0"
android:toAlpha="1.0" />
<translate
android:fromXDelta="500"
android:toXDelta="0" />
</set>
最后在ViewGroup中指定android:LayoutAnimation屬性即可:
<ListView
...
android:LayoutAnimation="@anim/anim_layout.xml"
...
/>
2.Activity的切換效果
使用方法:Activity的切換我們也可以使用自定義的效果造成,這里時主要用到overridePending Transition(int enterAnim,int exitAnim)這個方法,其中enterAnim表示的是Activity被打開時的動畫資源id雄嚣,exitAnim時Activity被暫停時的動畫資源id晒屎。具體的使用方法如下:
Intent intent = new Intent(FirstActivity.this,SecondActivity.class);
startActivity(intent);
overridePendingTransition(R.anim.enter_anim,R.anim.exit_anim);
public void finish(){
super.finish();
overridePendingTransition(R.anim.enter_anim,R.anim.exit_anim);
}
注意:overridePending Transition(int enterAnim,int exitAnim)方法必須要在startActivity()或者是finish()之后被調(diào)用才能生效。
三.屬性動畫
屬性動畫時API11新加入的特性缓升,和View動畫所不同的是鼓鲁,它對作用對象進(jìn)行了拓展,屬性動畫可以對任何對象(甚至不是對象的)做動畫港谊,并且不再拘泥于View動畫的5種模式骇吭。
1.使用屬性動畫
實(shí)現(xiàn)原理:屬性動畫是在一個時間間隔內(nèi)完成對象從一個屬性值到另一個屬性值的改變。在屬性動畫中幾個比較常用的動畫類是:ValueAnimator歧寺、ObjectAnimator和AnimmatorSet燥狰,其中ObjectAnimator繼承自ValueAnimator,而AnimmatorSet則表示一個動畫的集合斜筐。
操作方法:舉例來說:
(1)讓一個對象沿著y軸向上平移一段距離:
ObjectAnimator.ofFloat(myObject,"translationY",-myObject.getHeight()).start();
(2)改變一個對象的背景色屬性:
ValueAnimator colorAnim = ObjectAnimator.ofInt(this,"backgroundColor",0xfff8080,0xff8080ff); //實(shí)現(xiàn)從0xfff8080到0xff8080ff的顏色漸變
colorAnim.setDuration(3000); //設(shè)置時間
colorAnim.setEvaluator(new ArgbEvaluator());
colorAnim.setRepeatCount(ValueAnimator.INFINITE); //設(shè)置循環(huán)的次數(shù)
colorAnim.setRepeatMode(ValueAnimator.REVERSE); //動畫的模式
colorAnim.start();
除了可以使用代碼來動態(tài)的創(chuàng)建動畫外龙致,也可以使用XML來靜態(tài)的創(chuàng)建動畫,屬性動畫需要定義再res/amimator目錄下顷链,其中<set>標(biāo)簽對應(yīng)著AnimatorSet目代,<animator>對應(yīng)著valueAnimator,而<objectAnimator>則對應(yīng)著ObjectAnimator嗤练。舉例來說:
// res/animator/animator.xml
<set android:ordering="together" 設(shè)置動畫組的播放順序榛了,這里是順序播放
<objectAnimator
android:propertyName="x" 改變屬性的名稱
android:duration="300" 持續(xù)時間
android:valueTo="200" 屬性改變之后的值
android:valueType="intType"/> 指定屬性類型為整型
<objectAnimator
android:propertyName="y"
android:duration="300"
android:valueTo="300"
android:valueType="intType"/>
</set>
AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(myContext,R.anim.animator); //設(shè)置動畫
set.setTarget(mButton); //設(shè)置控件
set.start();
2.插值器和估值器
插值器的概念:即TimeInterpolator,它的作用是根據(jù)時間流逝的百分比來計算出當(dāng)前屬性值改變的百分比煞抬。系統(tǒng)預(yù)置的插值器有:LinearInterpolator(勻速)霜大、AcclerateDecelerateInterpolat-or(兩頭慢中間快)和DecelerateInterpolator(越來越慢)。
估值器的概念:即TypeEvaluator革答,它的作用是根據(jù)當(dāng)前屬性改變的百分比來計算改變后的屬性战坤。系統(tǒng)預(yù)置的估值器有IntEvaluator(整型)遮婶、FloatEvaluator(浮點(diǎn)型)和ArgeEvaluator(Color屬性)。
工作過程:
4.屬性動畫的監(jiān)聽器
監(jiān)聽器的種類:屬性動畫的監(jiān)聽器主要用于監(jiān)聽動畫的播放過程湖笨,主要是有如下的兩個接口:AnimatorUpdateListener和AnimatorListener旗扑。
監(jiān)聽器的定義:
(1)AnimationListener
public static interface AnimatorListener{
void onAnimationStart(Animator animation); //動畫開始
void onAnimationEnd(Animator animation); //動畫結(jié)束
void onAnimationCancel(Animator animation); //動畫取消
void onAnimationRepeat(Animator animation); //動畫重復(fù)
}
(2)AnimatorUpdateListener
public static interface AnimatorUpdateListener{
void onAnimationUpdate(ValueAnimator animation); //當(dāng)動畫的某一幀出現(xiàn)改變時就會被調(diào)用
}
5.對任意屬性做動畫
屬性動畫的原理:屬性動畫的要求時被動畫作用的對象能夠提供該屬性的get和set方法,屬性動畫就根據(jù)外界傳遞的該屬性的初始值和最終值慈省,以動畫的效果多次去調(diào)用set方法臀防,直到所傳遞的值達(dá)到于最終值。
實(shí)現(xiàn)屬性動畫的條件:基于上述的原理边败,我們時能夠?qū)δ骋粚ο螅╫bject)的任意屬性(abc)設(shè)置屬性動畫的袱衷,不過如果想讓動畫生效,還是需要同時滿足以下兩個條件的:
1)object必須提供setAbc()方法笑窜,如果動畫的時候沒有提供初始值致燥,則還需要提供getAbc()方法來獲取到該屬性的初始值。
2)object的setAbc()對屬性abc所做的改變必須能夠通過某種形式反映出來排截,否則動畫無效嫌蚤。
對于無法滿足條件的對象解決方案:從上面可以看出我們?nèi)绻獙δ骋粚ο髮?shí)現(xiàn)屬性動畫,就必須要滿足它所要求的兩個條件断傲,但是在很多情況下我們的對象是無法滿足這些條件的脱吱,針對這些情況,Android官方提供了3種解決方法:
給你的對象加上get()和set()方法
這種方式是最簡單粗暴的认罩,不過在絕大多數(shù)情況下我們都會因?yàn)闆]有足夠的權(quán)限而無法給某一對象加上get()和set()方法箱蝠,因?yàn)檫@些對象大都是在Android SDK內(nèi)部自定義好的。用一個類來包裝原始對象垦垂,間接為其提供get()和set()方法
這種方法也比較好理解宦搬,舉例來說:
public void performAnimate(){
ViewWrapper wrapper = new ViewWrapper(mButton);
ObjectAnimator.ofInt(wrapper,"width",500).setDuration(5000).start();
}
@Override
public void onClick(View view){
if(v == mButton){
performAnimate();
}
}
private static class ViewWrapper{ //用類來封裝get和set方法
private View mTarget;
public ViewWrapper(View target){
mTarget = target;
}
public int getWidth(){
return mTarget.getLayoutParams().width;
}
public void setWidth(int width){
mTarget.getLayoutParams().width = width;
mTarget.requestLayout();
}
}
- 采用ValueAnimator,監(jiān)聽動畫過程劫拗,自己實(shí)現(xiàn)屬性的改變
ValueAnimator本身不作用于任何對象间校,但是它可以對一個值做動畫,然后我們就可以監(jiān)聽其動畫過程杨幼,在動畫過程中修改我們的對象屬性值撇簿,舉例來說:
private void performAnimate(final View target,final int start,final int end){
ValueAnimator valueAnimator = new ValueAnimator.ofInt(1,100); //設(shè)置時間
ValueAnimator.addUpdateListener(new AnimatorUpdateListener(){
private IntEvaluator mEvaluator = new IntEvaluator(); //設(shè)置一個估值器
@Override
public void onAnimationUpdate(ValueAnimator animation){
int currentValue = (Integer) animator.getAnimatedValue(); //獲得當(dāng)前動畫的進(jìn)度
float fraction = animator.getAnimatedFraction(); //獲得當(dāng)前進(jìn)度占整個動畫的過程的比例
target.getLayoutParams.width() = mEvaluator.evaluate(fraction,start,end); //使用估值器進(jìn)行計算
target.requestLayout();
}
});
valueAnimator.setDuration(5000).start();
}
@Override
public void onClick(View v){
if(v == mButton){
performAnimate(mButton,mButton.getWidth(),500);
}
}
四.使用動畫的注意事項(xiàng)
OOM問題
當(dāng)圖片數(shù)量較多且圖片較大時就很容易出現(xiàn)OOM,這種情況大多發(fā)生在幀動畫當(dāng)中差购。內(nèi)存泄漏
在屬性動畫中有一類無限循環(huán)的動畫,在使用這些動畫時我們需要記住在Activity退出時必須要對動畫進(jìn)行停止汉嗽,否則將導(dǎo)致Activity無法釋放從而造成內(nèi)存泄漏(View動畫不存在此問題)衅疙。兼容性問題
動畫在3.0一下的系統(tǒng)中存在兼容性問題挨队,需要注意。View動畫的問題
View動畫是對View的影像做動畫螟够,并不是真正改變View的狀態(tài),所以有的時候會出現(xiàn)View動畫完成之后無法隱藏的現(xiàn)象驯嘱,這個時候只需要調(diào)用view.clearAnimation()清除掉View動畫即可。不要使用px
在進(jìn)行動畫的是由盡量使用dp,px會在不同的設(shè)備上有不同的效果诚纸。動畫元素的交互
從Android3.0之后,屬性動畫的單擊事件觸發(fā)位置為移動后的位置陈惰,但是View動畫仍然是停留在原位置畦徘。硬件加速
在使用動畫的過程中,建議采用硬件加速抬闯。