Android 動畫詳解:屬性動畫、View 動畫和幀動畫

?前言

Android動畫是面試的時候經常被問到的話題。我們都知道Android動畫分為三類:View動畫、幀動畫和屬性動畫。

先對這三種動畫做一個概述:

View動畫是一種漸進式動畫,定義動畫開始和結束的兩幀,并指定動畫變化的時間和方式。并通過平移、縮放、旋轉和透明度四種效果結合成復雜的動畫效果。而在開始和結束幀之間插入的漸變值依據的是插值器。

幀動畫是通過不停的切換圖片實現動畫效果。

屬性動畫是不停的改變對象的屬性來實現動畫效果。4.4新出的過渡動畫只是對屬性動畫的一層封裝。

本文原創,轉載請注明出處:http://blog.csdn.net/seu_calvin/article/details/52724655

1. ?View動畫??

1.1?系統提供的四種View動畫(補間動畫)

View動畫可以在res/anim/name.xml文件里進行配置,四種View動畫的漸變式變換分別對應<translate>、<scale>、<rotate>、<alpha>四個標簽,動畫集合可以使用<set>標簽。xml的各個動畫屬性比較簡單,這里就不再貼實例代碼了。只需要注意如何應用配置好的xml文件來啟動動畫即可:

view.startAnimation(AnimationUtils.loadAnimation(this,R.anim.myanimation));

這些當然也可以在Java代碼里進行配置,也比較簡單,這里寫了一個示例代碼:

splash = (RelativeLayout)findViewById(R.id.splash);

//旋轉動畫

RotateAnimation rotateAnimation =newRotateAnimation(0,360,

Animation.RELATIVE_TO_SELF,0.5f,Animation.RELATIVE_TO_SELF,0.5f);

rotateAnimation.setDuration(2000);

rotateAnimation.setFillAfter(true);

//縮放動畫

ScaleAnimation scaleAnimation =newScaleAnimation(0,1,0,1,

Animation.RELATIVE_TO_SELF,0.5f,Animation.RELATIVE_TO_SELF,0.5f);

scaleAnimation.setDuration(2000);

scaleAnimation.setFillAfter(true);

//漸變動畫

AlphaAnimation alphaAnimation =newAlphaAnimation(0.2f,1.0f);

alphaAnimation.setDuration(2000);

alphaAnimation.setFillAfter(true);

//平移動畫

TranslateAnimation translateAnimation = newTranslateAnimation (0,0,100,100);

translateAnimation.setDuration(2000);

translateAnimation.setFillAfter(true);

//動畫集合

AnimationSet animationSet =newAnimationSet(true);

animationSet.addAnimation(rotateAnimation);

animationSet.addAnimation(scaleAnimation);

animationSet.addAnimation(alphaAnimation);

animationSet.addAnimation(translateAnimation);

//啟動動畫

plash.startAnimation(animationSet);

1.2 ??自定義View動畫

實際項目中,如果四種基本動畫無法滿足需求,就需要自定義補間動畫了。

完成自定義動畫需要繼承Animation類,并重寫其initialize()以及applyTransformation()。前者用于一些初始化的操作,后者用于進行矩陣變換。

1.3?????為ViewGroup的所有子元素設置動畫

上面1.1,1.2都是給View設置動畫效果,Android同樣提供了為ViewGroup設置android:layoutAnimation=”@anim/layout_anim”來達到給ViewGroup中所有子元素設置動畫的目的。下面給出相關代碼:

//res/anim/anim/layout_anim.xml

android:delay=”0.1”//動畫延遲時間為0.1*T,本例為100ms

android:animationOrder=”normal”//子元素的播放動畫順序為順序,也有reverse以及random

android: animation=”@anim/layout_anim_item”/>

//res/anim/anim/layout_anim_item.xml


animation:duration=”200”//每個子元素的動畫周期T

animation:interpolator=”@android:anim/accelerate_ interpolator”//指定插值器

animation:shareInterpolator=”true”>//表示所有子元素共享該插值器

</set>

1.4 ? ??為Activity切換設置動畫

估計大家也都用過,在startActivity()之后使用,使Activity切換時達到一個平移的動畫效果:

overridePendingTransition(R.anim.tran_in,R.anim.tran_out);

//res/anim/tran_in


android:duration="500"

//表示從屏幕100%的位置開始,因此tran_out當然是toXDelta="-100%p",其他不變

android:fromXDelta="100%p"

android:fromYDelta="0"

android:toXDelta="0"

android:toYDelta="0">

</translate>

2. ??幀動畫

上面也提到了,幀動畫就是不停的切換圖片實現動畫效果。很明顯容易OOM,所以使用幀動畫要注意圖片大小。

幀動畫的使用也很簡單,使用示例如下:

//res/drawable/myanimation.xml


animation:oneshot=”false” >//false為循環播放,true為類似于View動畫的setFillAfter效果

</animation-list>

//在代碼里加載動畫設置并啟動動畫

view.setBackgroundResource(R.drawable.myanimation.xml);

(AnimationDrawable)view.getBackground.start();

3.?屬性動畫

View動畫的那四種效果有很明顯的缺點,繪制出來的效果其實并沒有真正改變View的屬性,即left、top、right和bottom的值,只是系統臨時繪制的結果。這樣View的點擊位置并沒有發生變化。針對這個問題,從Android3.0開始屬性動畫應運而生。

屬性動畫本質是通過改變新增的屬性(如平移translationX/Y、縮放scaleX/Y、旋轉rotationX/Y等)并刷新屏幕來實現動畫效果,并且實現點擊位置的實時改變。但是屬性動畫仍然不會修改原始的上下左右四個值。最后需要注意的是,屬性動畫不止用于View,還可以用于任何對象。

下面介紹與屬性動畫相關的類和方法:


3.1? setTranslationX方法

該方法直接更改view屬性的方法,因為有時候不需要使用動畫效果。

view.setTranslationX(x);//3.0以后

ViewHelper.setTranslationX(view,x);//3.0以前通過NineOldAndroid庫實現

3.2 ? ValueAnimator類

ValueAnimator只定義和執行動畫流程,并沒有直接操作屬性值的邏輯,需要添加動畫更新的監聽,并在onAnimationUpdate()中執行自定義的動畫邏輯。

ValueAnimator animator = ValueAnimator.ofInt(1,100);//定義動畫,相當于1秒內數100個數

animator.addUpdateListener(newAnimatorUpdateListener() {

@Override

publicvoidonAnimationUpdate(ValueAnimator animation){

floatfraction = animation.getAnimatedFraction();//動畫進度值0-1

//整型估值器幫我們計算了start+(end-strat)*fraction,并設置給控件的寬度

view.getLayoutParams().width =newIntEvaluator().evaluate(fraction,start,end)//不需要set方法

? ? ? ? view.requestLayout();

? ? }

});

animator.setDuration(1000).start();

3.3 ? ?ObjectAnimator類

ObjectAnimator繼承自ValueAnimator,它允許直接改變view的屬性,下面通過一個例子介紹。

//x軸方向縮放的例子

ObjectAnimator animator = ObjectAnimator.ofFloat(view,”scaleX”,2.0f);

animator.setDuration(1000);

animator.setStartDelay(1000);

animator.start();

大多數的情況使用ObjectAnimator就足夠了,因為它不用像ValueAnimator那樣自己寫動畫更新的邏輯,但是ObjectAnimator有一定的限制——它需要目標屬性提供指定的處理方法(譬如提供get/set方法),這是因為ObjectAnimator的原理是不停的調用set方法更新屬性值,并且如果我們沒有傳遞初始值,系統會直接調用get方法獲取值。而上面3.2中介紹過的ValueAnimator則不直接操作屬性值,所以要操作對象的屬性可以不需要se/get方法,你完全可以通過當前動畫的計算去修改任何屬性。

針對這個問題,官方推薦我們用一個類包裝原始對象,間接為其提供get/set方法,實現起來很簡單,實例如下:

ViewWrapper wrapper =newViewWrapper(view);

ObjectAnimator.ofInt(wrapper,”width”,200).setDuration(1000).start();

private ? static ? ?class ? ViewWrapper{

private ?View myView;

public ? View ?Wrapper(View view){

? ? ? myView = view;

? ? }

public ?int ? getWidth(){

returnmyView.getLayoutParams().width;

? ? }

public ? int ?setWidth(intwidth){

? ? ? myView.getLayoutParams().width = width;

? ? ? myView.requestLayout();

? ? }

}

3.4 ?ViewPropertyAnimation類

ViewPropertyAnimation是NineOldAndroid庫中的類,簡化了ObjectAnimator類的操作,并且NineOldAndroid庫兼容了3.0以前的Android版本。下面經過一個例子介紹。

//x軸方向縮放的例子,效果同3.3

ViewPropertyAnimation.animate(view).scaleX(2.0f).setDuration(1000)

.setInterpolator(newOvershootInterpolator())

.setStartDelay(1000).start();

3.5? AnimationSet類

動畫集合,提供把多個動畫組合成一個組合的機制,并可設置動畫的時序關系,如同時播放、順序播放或延遲播放。具體使用方法比較簡單,如下所示:

ObjectAnimator objectAnimator1= ObjectAnimator.ofFloat(view,"alpha",1.0f,0f);

ObjectAnimator objectAnimator2= ObjectAnimator.ofFloat(view,"translationY",0f,30f);

ObjectAnimator objectAnimator3= ObjectAnimator.ofFloat(view,"translationX",0f,30f);

AnimatorSet animatorSet =newAnimatorSet();

animatorSet.setDuration(5000);

animatorSet.setInterpolator(newLinearInterpolator());

// animatorSet.playTogether(objectAnimator1, objectAnimator2. objectAnimator3); //三個動畫同時執行?

// 12同時執行,3接著執行

animatorSet.play(objectAnimator1).with(objectAnimator2);?

animatorSet.play(objectAnimator3).after(objectAnimator2);?

animatorSet.start();

4.?插值器總結

4.1?系統已經提供給我們的插值器

各種插值器都是實現了Interpolator接口,下面來看一下系統已經提供給我們直接使用的插值器。


4.2 ?自定義插值器

Interpolator都實現了Interpolator接口,而Interpolator接口又繼承自TimeInterpolator,TimeInterpolator接口定義了一個由系統調用的getInterpolation(float input)方法,其中參數input代表動畫完成進度,在0和1之間。我們自定義插值器只需要實現Interpolator接口并覆寫getInterpolation()方法即可實現自定義的動畫效果。


如下就是一個動畫始末速率較慢、中間加速的AccelerateDecelerateInterpolator插值器:

public ? class ? ?AccelerateDecelerateInterpolator ? ?extends ? BaseInterpolator

implements ? ? ? ?NativeInterpolatorFactory{

? ? ......

public ? ? ? float ? ? ?getInterpolation(floatinput){

return(float)(Math.cos((input +1) * Math.PI) /2.0f) +0.5f;

? ? }

? ? ......

}

5.?動畫監聽器

我們在平時開發過程中,經常要監聽動畫完成的時機以繼續業務邏輯,那么我們可以通過給動畫集合設置AnimationListener監聽器來實現。分別可以監聽動畫開始、結束、取消以及重復播放。

//監聽動畫完成

animationSet.setAnimationListener(newAnimation.AnimationListener() {

@Override

publicvoidonAnimationStart(Animation animation){}

@Override

public ? ?void ? ? onAnimationEnd(Animation animation){}

@Override

public ? ?void ? ? onAnimationRepeat(Animation animation){}

@Override

public ? ?void ? ? onAnimationCancel(Animation animation){}

});

最后若想監聽動畫中每一幀的回調,我們可以設置AnimatorUpdateListener監聽器并重寫其onAnimationUpdate()方法即可。

至此關于Android動畫的知識總結完畢。

轉載請注明出處:http://blog.csdn.net/seu_calvin/article/details/52724655

想對作者說點什么??我來說一句

?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,401評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,011評論 3 413
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,263評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,543評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,323評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,874評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,968評論 3 439
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,095評論 0 286
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,605評論 1 331
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,551評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,720評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,242評論 5 355
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 43,961評論 3 345
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,358評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,612評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,330評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,690評論 2 370

推薦閱讀更多精彩內容