Android中的動(dòng)畫概述

動(dòng)畫可以分為三類:View動(dòng)畫,幀動(dòng)畫,屬性動(dòng)畫。

一、View動(dòng)畫

1.View動(dòng)畫包括四種:平移動(dòng)畫,縮放動(dòng)畫,旋轉(zhuǎn)動(dòng)畫,透明度動(dòng)畫。分別對(duì)應(yīng)著Animation的四個(gè)子類:TranslateAnimation,ScaleAnimation,RotateAnimation,AlphaAnimation。幀動(dòng)畫其實(shí)也是View動(dòng)畫的一種。

2.View動(dòng)畫是對(duì)View的影像做動(dòng)畫,并不是真正的改變View的位置等狀態(tài)。通過View動(dòng)畫將View平移后,新位置不能觸發(fā)點(diǎn)擊事件,老位置可以。

3.使用View動(dòng)畫,在動(dòng)畫完成后,有時(shí)候會(huì)出現(xiàn)View無法隱藏的現(xiàn)象,即設(shè)置setVisiable(View.GONE)沒有效果,這個(gè)時(shí)候只需要調(diào)用view.clearAnimation()清除View動(dòng)畫即可解決此問題。

4.View動(dòng)畫的使用:

通過XMl定義:Animation animation = AnimationUtils.loadAnimation(context,resId);

view.startAnimation(animation);

通過純代碼:

AlphaAnimation alphaAnimation = new AlphaAnimation(0,1);

alphaAnimation.setDuration(300);

view.startAnimation(alphaAnimation);

為動(dòng)畫設(shè)置監(jiān)聽:

animation.setAnimationListener(new Animation.AnimationListener());

5.自定義View動(dòng)畫:

繼承Animation類,重寫initialize和applyTransformation方法,在initialize方法中做一些初始化工作,在applyTransformation中進(jìn)行相應(yīng)的矩陣變換。很多時(shí)候需要用到Camera來簡(jiǎn)化矩陣變換的過程,需要用到數(shù)學(xué)上面的東西。實(shí)際開發(fā)中很少用到自定義View動(dòng)畫。

二、幀動(dòng)畫

1.幀動(dòng)畫是順序播放一組預(yù)先定義好的圖片,類似于電影播放。對(duì)應(yīng)于AnimationDrawable類。

XML中的定義方式如下(在drawable文件夾中):

然后將上訴Drawable作為View的背景并通過AnimationDrawable來播放:

view.setBackgroundResource(R.drawable.resid);

AnimationDrawable drawable = view.getBackground();

drawable.start();

2.幀動(dòng)畫使用比較簡(jiǎn)單,但是比較容易引起OOM,所以在使用幀動(dòng)畫時(shí)應(yīng)盡量避免使用過多尺寸較大的圖片。

3.View動(dòng)畫的一個(gè)特殊使用場(chǎng)景,就是為ViewGroup中的所有子元素添加出場(chǎng)效果,需要用到LayoutAnimation。

定義LayoutAnimation:

android:delay="0.5"

android:animationOrder="normal"

android:animation="@anim/anim_item">

其中anim_item就是具體的View動(dòng)畫,然后為ViewGroup指定android:layoutAnimation屬性 android:layoutAnimation=“@anim/layout_animation”;

4.除了在XML中指定LayoutAnimation外,還可以通過LayoutAnimationController來實(shí)現(xiàn):

Animation animation = AnimationUtils.loadAnimation(context,resid);

LayoutAnimationController controller = new LayoutAnimationController(animation);

controller.setDelay(0.5f);

controller.setOrder(LayoutAnimationController.ORDER_NORMAL);

viewGroup.setLayoutAnimation(controller);

5.Activity的切換效果:

調(diào)用overridePendingTransition(resid,resid),但是必須在startActivity跟finish之后調(diào)用才有效果!

三、屬性動(dòng)畫

1.屬性動(dòng)畫是API 11(3.1) 新加入的特性,和View動(dòng)畫不同,它對(duì)作用對(duì)象進(jìn)行了擴(kuò)展,屬性動(dòng)畫可以對(duì)任何對(duì)象做動(dòng)畫,甚至還可以沒有對(duì)象。

動(dòng)畫默認(rèn)時(shí)間間隔300ms,默認(rèn)幀率10ms/幀。其可以達(dá)到的效果是:在一個(gè)時(shí)間間隔內(nèi)完成對(duì)象從一個(gè)屬性值到另一個(gè)屬性值的改變。

2.比較常用的幾個(gè)動(dòng)畫類:ValueAnimator,ObjectAnimator,AnimatorSet。其中ObjectAnimator繼承自ValueAnimator,AnimatorSet和ValueAnimator都繼承自Animator。

AnimatorSet是個(gè)動(dòng)畫集合,可以定義一組動(dòng)畫。

3.Animator是個(gè)抽象類,實(shí)現(xiàn)了Cloneable接口,Cloneable接口里面什么都沒有。

4.ValueAnimator不能對(duì)具體的某個(gè)屬性做動(dòng)畫,但是可以對(duì)一個(gè)值做動(dòng)畫,就是實(shí)現(xiàn)值的漸變。例如:ValueAnimator.ofInt(1.100)。具體的對(duì)某個(gè)屬性值的動(dòng)畫的實(shí)現(xiàn),在它的子類ObjectAnimator中。不過可以通過ValueAnimator對(duì)值的漸變,結(jié)合AnimatorUpdateListener可以做很多事情(包括實(shí)現(xiàn)屬性動(dòng)畫)。

5.使用方法示例:

通過代碼:ObjectAnimator.ofFloat(view,"propertyName",value).start();

通過XML:屬性動(dòng)畫需要定義在res/animator/目錄下面,語(yǔ)法如下:

android:ordering="together">

android:propertyName="x"

android:duration="300"

android:valueTo="200"

android:valueType="floatType"/>

android:propertyName="y"

android:duration="300"

android:valueTo="300"

android:valueType="floatType"/>

一個(gè)下面可以包含多個(gè)。

AnimatorSet set = AnimatorSet.loadAnimator(context,resid);

set.setTarget(view);

set.start();

6.插值器與估值器

插值器:根據(jù)時(shí)間流逝的百分比來計(jì)算出當(dāng)前屬性值改變的百分比。TimeInterpolator

系統(tǒng)預(yù)置的有LinearInterpolator(線性插值器:勻速動(dòng)畫)、AccelerateDecelerateInterpolator(加速減速插值器:動(dòng)畫兩頭慢,中間快)、DecelerateInterpolator(減速插值器:動(dòng)畫越來越慢)等。

這些插值器都繼承自BaseInterpolator,BaseInterpolator實(shí)現(xiàn)了Interpolator接口,而Interpolator幾口繼承自TimeInterpolator接口。TimeInterpolator接口定義一個(gè)方法叫:

public float getInterpolation(float intput); 所以自定義插值器的話,只需要實(shí)現(xiàn)Interpolator或者TimeInterpolator接口。

估值器:根據(jù)當(dāng)前屬性改變的百分比來計(jì)算改變后的屬性值。TypeEvaluator

系統(tǒng)預(yù)置的估值器有IntEvaluator(針對(duì)整型屬性)、FloatEvaluator(針對(duì)浮點(diǎn)型)、ArgbEvaluator(針對(duì)Color屬性)。

它們都實(shí)現(xiàn)了TypeEvaluator接口,TypeEvaluator接口中定義了一個(gè)方法:

public T evaluate(float fraction, T startValue, T endValue);

7.屬性動(dòng)畫要求對(duì)象的該屬性必須有set方法,get方法可選(如果提供了動(dòng)畫的初始值,則不需要get方法,若沒有提供初始值,那么系統(tǒng)會(huì)調(diào)用get方法獲取初始值)。

8.對(duì)任意屬性做動(dòng)畫:如果對(duì)象沒有該屬性的set或者get方法,可以通過如下3種方式解決:

①:給對(duì)象加上get和set方法,如果有權(quán)限的話。

②:用一個(gè)類來包裝原始對(duì)象,間接為其提供get,set方法。(此方法比較常用)

③:采用ValueAnimator,監(jiān)聽動(dòng)畫過程,自己實(shí)現(xiàn)屬性的改變。

關(guān)于方法2的例子:

例如如果對(duì)Button的width屬性做動(dòng)畫,但是Button的width的set方法是設(shè)置最大跟最小寬度,而不是改變其寬度。get方法是獲取寬度。這樣的話直接對(duì)width屬性做動(dòng)畫是沒有效果的,因?yàn)楦静皇窃O(shè)置的那個(gè)我們想改變的寬度。這樣我們可以通過一個(gè)類去包裝Button,然后在這個(gè)類的setWidth方法中,去

button.getLayoutParams().width = width.

button.requestLayout();

這樣就間接的給Button的寬度做了動(dòng)畫。因?yàn)橹苯訛檫@個(gè)寬度去加set方法是行不通的,Button封裝在SDK中,我們改變不了。

9.在動(dòng)畫的內(nèi)部,get,set方法的調(diào)用是通過反射來實(shí)現(xiàn)的。

注意:屬性動(dòng)畫必須運(yùn)行在有Looper的線程中,否則會(huì)拋出“Animators may only be run on Looper threads”異常。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1 背景 不能只分析源碼呀,分析的同時(shí)也要整理歸納基礎(chǔ)知識(shí),剛好有人微博私信讓全面說說Android的動(dòng)畫,所以今...
    未聞椛洺閱讀 2,851評(píng)論 0 10
  • 概述 在Android開發(fā)的過程中,View的變化是很常見的,如果View變化的過程沒有動(dòng)畫來過渡而是瞬間完成,會(huì)...
    小蕓論閱讀 39,161評(píng)論 18 134
  • Animation Animation類是所有動(dòng)畫(scale、alpha、translate、rotate)的基...
    四月一號(hào)閱讀 2,030評(píng)論 0 10
  • 將薄毯蓋好 手腳放好 將冷氣赫茲調(diào)好 窗簾對(duì)齊邊角擺好 暗房里沒有相片 鏡頭收好 急著刷分貝的馬達(dá) 沖向救護(hù)室的擔(dān)...
    Oran閱讀 193評(píng)論 0 0
  • 漸漸有了自己的想法說起孤獨(dú),可謂生命的常態(tài)吧。 小時(shí)候,天真無邪,以為所能看到的天空就是整個(gè)世界。 隨著歲月的洗禮...
    波斯女神閱讀 202評(píng)論 0 1

友情鏈接更多精彩內(nèi)容