Android進(jìn)階(7)| 動畫

本節(jié)目錄

一.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動畫仍然是停留在原位置畦徘。

  • 硬件加速
    在使用動畫的過程中,建議采用硬件加速抬闯。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末井辆,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子溶握,更是在濱河造成了極大的恐慌杯缺,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,185評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件睡榆,死亡現(xiàn)場離奇詭異萍肆,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)胀屿,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,652評論 3 393
  • 文/潘曉璐 我一進(jìn)店門匾鸥,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人碉纳,你說我怎么就攤上這事勿负。” “怎么了劳曹?”我有些...
    開封第一講書人閱讀 163,524評論 0 353
  • 文/不壞的土叔 我叫張陵奴愉,是天一觀的道長。 經(jīng)常有香客問我铁孵,道長锭硼,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,339評論 1 293
  • 正文 為了忘掉前任蜕劝,我火速辦了婚禮檀头,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘岖沛。我一直安慰自己暑始,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,387評論 6 391
  • 文/花漫 我一把揭開白布婴削。 她就那樣靜靜地躺著廊镜,像睡著了一般。 火紅的嫁衣襯著肌膚如雪唉俗。 梳的紋絲不亂的頭發(fā)上嗤朴,一...
    開封第一講書人閱讀 51,287評論 1 301
  • 那天配椭,我揣著相機(jī)與錄音,去河邊找鬼雹姊。 笑死股缸,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的吱雏。 我是一名探鬼主播敦姻,決...
    沈念sama閱讀 40,130評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼坎背!你這毒婦竟也來了替劈?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,985評論 0 275
  • 序言:老撾萬榮一對情侶失蹤得滤,失蹤者是張志新(化名)和其女友劉穎陨献,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體懂更,經(jīng)...
    沈念sama閱讀 45,420評論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡眨业,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,617評論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了沮协。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片龄捡。...
    茶點(diǎn)故事閱讀 39,779評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖慷暂,靈堂內(nèi)的尸體忽然破棺而出聘殖,到底是詐尸還是另有隱情,我是刑警寧澤行瑞,帶...
    沈念sama閱讀 35,477評論 5 345
  • 正文 年R本政府宣布奸腺,位于F島的核電站,受9級特大地震影響血久,放射性物質(zhì)發(fā)生泄漏突照。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,088評論 3 328
  • 文/蒙蒙 一氧吐、第九天 我趴在偏房一處隱蔽的房頂上張望讹蘑。 院中可真熱鬧,春花似錦筑舅、人聲如沸座慰。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,716評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽角骤。三九已至,卻和暖如春心剥,著一層夾襖步出監(jiān)牢的瞬間邦尊,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,857評論 1 269
  • 我被黑心中介騙來泰國打工优烧, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留蝉揍,地道東北人。 一個月前我還...
    沈念sama閱讀 47,876評論 2 370
  • 正文 我出身青樓畦娄,卻偏偏與公主長得像又沾,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子熙卡,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,700評論 2 354

推薦閱讀更多精彩內(nèi)容

  • 【Android 動畫】 動畫分類補(bǔ)間動畫(Tween動畫)幀動畫(Frame 動畫)屬性動畫(Property ...
    Rtia閱讀 6,152評論 1 38
  • 1 背景 不能只分析源碼呀杖刷,分析的同時也要整理歸納基礎(chǔ)知識,剛好有人微博私信讓全面說說Android的動畫驳癌,所以今...
    未聞椛洺閱讀 2,705評論 0 10
  • 轉(zhuǎn)載一篇高質(zhì)量博文滑燃,原地址請戳這里轉(zhuǎn)載下來方便今后查看。1 背景不能只分析源碼呀颓鲜,分析的同時也要整理歸納基礎(chǔ)知識表窘,...
    Elder閱讀 1,942評論 0 24
  • 一: 傳統(tǒng) View 動畫(Tween/Frame) 1.1 Tween 動畫 主要有 4 中:縮放、平移甜滨、漸變乐严、...
    dfg_fly閱讀 719評論 1 2
  • 1 背景 不能只分析源碼呀,分析的同時也要整理歸納基礎(chǔ)知識衣摩,剛好有人微博私信讓全面說說Android的動畫昂验,所以今...
    lisx_閱讀 964評論 0 0