Android幾種動畫的總結(jié)(逐幀動畫、補間動畫)

逐幀動畫

逐幀動畫也叫 Drawable Animation缘眶,是最簡單最直觀的動畫效果嘱根。

在Android 中實現(xiàn)逐幀動畫就是由設(shè)計師給出一系列狀態(tài)不斷變化的圖片,開發(fā)者就指定這些圖片顯示的持續(xù)時間巷懈,然后順序開始播放這些圖片该抒,就形成了動畫了。

使用逐幀動畫 既可以使用XML的方法實現(xiàn)顶燕,也可以使用代碼來實現(xiàn)凑保。

XML

首先把資源文件(每一幀的圖片)放在 res/drawable 下。 如圖:

然后在這里 新建一個XML文件涌攻。 在這個文件中使用的 <animation-list>標(biāo)簽來定義動畫欧引。使用<item>標(biāo)簽來定義動畫的每一幀,并在每一個<item>中指定自己的屬性癣漆,例如 持續(xù)時間 android:duration="300" 维咸、 這一幀使用的圖片 android:drawable="@drawable/z_1_die_01" 。

frme_animation.xml

<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="false">

    <item
        android:drawable="@drawable/z_1_die_01"
        android:duration="300"/>
    <item
        android:drawable="@drawable/z_1_die_02"
        android:duration="300"/>
    <item
        android:drawable="@drawable/z_1_die_03"
        android:duration="300"/>
    <item
        android:drawable="@drawable/z_1_die_04"
        android:duration="300"/>
    <item
        android:drawable="@drawable/z_1_die_05"
        android:duration="300"/>

</animation-list>

android:oneshot 來控制動畫是否循環(huán)播放惠爽, false 表示 循環(huán)播放 癌蓖, true 表示 不循環(huán)播放 。

在控件的布局中給控件使用這個 drawable 文件

<ImageView
android:id="@+id/iv_frame_xml"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/frme_animation"/>

定義好了這個動畫婚肆,為了讓動畫播放租副,就要使用代碼讓他開始播放,代碼如下:

//xml
ImageView ivFrameXml = (ImageView) findViewById(R.id.iv_frame_xml);
AnimationDrawable background = (AnimationDrawable)ivFrameXml.getDrawable();
background.start();

代碼方式

代碼的方式更加簡單较性,新建一個 AnimationDrawable 用僧,并為他增加每一幀的圖片和持續(xù)時間就可以了。

//code
ImageView ivFrameCode = (ImageView) findViewById(R.id.iv_frame_code);
AnimationDrawable animationDrawable = new AnimationDrawable();
for (int i = 1; i <= 5; i++) {
    int id = getResources().getIdentifier("z_1_die_0" + i, "drawable", getPackageName());
    Drawable drawable = getResources().getDrawable(id);
    animationDrawable.addFrame(drawable,300);
}
ivFrameCode.setImageDrawable(animationDrawable);
    //循環(huán)播放
animationDrawable.setOneShot(false);
    //開始播放
animationDrawable.start();

效果如圖所示:

補間動畫

補間動畫無須再知道動畫過程中的每一幀了赞咙,只需要定義動畫的開始和結(jié)束责循,并且指定變化的時間和方式就可以了,他會自動補全中間的過程攀操。Android會通過所給出的開始值與結(jié)束值院仿,再根據(jù)中間變化的規(guī)律,最后計算出每一幀圖片顯示的效果,最后直接顯示出來歹垫。

主要包括這四種基本效果:透明度變化 Alpha 剥汤、縮放變化 Scale 、 位移變化 Translate 排惨、旋轉(zhuǎn)變化 Rotate 吭敢。這四種效果可以動態(tài)組合,從而實現(xiàn)復(fù)雜的動畫暮芭。

插值器 Interpolator

補間動畫能夠自己補充中間的內(nèi)容鹿驼,其實靠的就是這個。

Interpolator 會根據(jù)類型不同谴麦,選擇不同的算法計算出補間動畫所需要動態(tài)插入的密度和位置蠢沿,Interpolator 負責(zé)控制動畫的變化速度,他可以 勻速匾效、加速、減速恤磷、拋物線等多種變化面哼。

public interface Interpolator extends TimeInterpolator {
    // A new interface, TimeInterpolator, was introduced for the new android.animation
    // package. This older Interpolator interface extends TimeInterpolator so that users of
    // the new Animator-based animations can use either the old Interpolator implementations or
    // new classes that implement TimeInterpolator directly.
}

public interface TimeInterpolator {

    /**
     * Maps a value representing the elapsed fraction of an animation to a value that represents
     * the interpolated fraction. This interpolated value is then multiplied by the change in
     * value of an animation to derive the animated value at the current elapsed animation time.
     *
     * @param input A value between 0 and 1.0 indicating our current point
     *        in the animation where 0 represents the start and 1.0 represents
     *        the end
     * @return The interpolation value. This value can be more than 1.0 for
     *         interpolators which overshoot their targets, or less than 0 for
     *         interpolators that undershoot their targets.
     */
    float getInterpolation(float input);
}

由上面的代碼可以清楚的看到一點,Interpolator 只是繼承于 TimeInterpolator 扫步,里面只是一個空實現(xiàn)而已魔策。而在 TimeInterpolator 下,也只有 float getInterpolation(float input); 一個方法河胎。input 是一個 0.0 ~ 1.0 的值 闯袒, 經(jīng)過自定義的方法 ,那么只要返回適當(dāng)?shù)闹涤卧溃敲淳湍軐崿F(xiàn)各種的效果政敢。

例如下面是系統(tǒng)實現(xiàn)的先加速后減速的Interpolator。

AccelerateDecelerateInterpolator

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

當(dāng)然Android SDK 中已經(jīng)實現(xiàn)了幾個 Interpolator 讓開發(fā)者直接使用胚迫。

下面繼續(xù)介紹動畫喷户,補間動畫和逐幀動畫一樣,既能使用XML實現(xiàn)也能使用Code實現(xiàn)访锻。

XML的文件應(yīng)放置在 res/anim 目錄上褪尝。

透明度變化 Alpha

XML

anim_tween_alpha.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
>

<alpha
    android:repeatMode="reverse"
    android:repeatCount="-1"
    android:duration="1000"
    android:fromAlpha="0"
    android:toAlpha="1" />

</set>

android:interpolator 用來指定插值器

android:repeatMode 重復(fù)的模式

android:repeatCount="-1" 重復(fù)的次數(shù)。 -1 為無限循環(huán)期犬。

XML寫完了河哑,就要在代碼中使用他了。

ImageView ivTweenXml = (ImageView) findViewById(R.id.iv_tween_xml);
AnimationSet alphaSet  = (AnimationSet) AnimationUtils.loadAnimation(TweenActivity.this,R.anim.anim_tween_alpha);
ivTweenXml.startAnimation(alphaSet);

Code

ImageView ivTweenCode = (ImageView) findViewById(R.id.iv_tween_code);
AlphaAnimation alphaAnimation = new AlphaAnimation(0, 1);
alphaAnimation.setDuration(1000);
alphaAnimation.setRepeatMode(Animation.REVERSE);
alphaAnimation.setRepeatCount(-1);
ivTweenCode.startAnimation(alphaAnimation);

上面都實現(xiàn)了透明度從0到1.

縮放變化 Scale

XML

anim_tween_scale.xml

<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/accelerate_decelerate_interpolator">

    <scale
        android:duration="1000"
        android:fromXScale="0.2"
        android:fromYScale="0.2"
        android:toXScale="1"
        android:toYScale="1"
        android:pivotX="50%"
        android:pivotY="50%"
        android:repeatCount="-1"
        android:repeatMode="reverse"
         />

</set>

  ImageView ivScaleXml = (ImageView) findViewById(R.id.iv_scale_xml);
  AnimationSet scaleSet  = (AnimationSet) AnimationUtils.loadAnimation(TweenActivity.this,R.anim.anim_tween_scale);
  ivScaleXml.startAnimation(scaleSet);

pivotX 中心點
直接寫數(shù)字代表 控件本身的坐標(biāo)系中的x的值
數(shù)字后面加了 % 例如 :50% 龟虎,代表 在本身的坐標(biāo)系中的 x軸長度的50%

Code

ImageView ivScaleCode = (ImageView) findViewById(R.id.iv_scale_code);
ScaleAnimation scaleAnimation = new ScaleAnimation(0.2f, 1, 0.2f, 1f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
scaleAnimation.setDuration(1000);
scaleAnimation.setRepeatMode(Animation.REVERSE);
scaleAnimation.setRepeatCount(-1);
ivScaleCode.startAnimation(scaleAnimation);

位移變化 Translate

XML

anim_tween_translate.xml

<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/accelerate_decelerate_interpolator">

    <translate
        android:duration="1000"
        android:fromXDelta="0"
        android:fromYDelta="0"
        android:toXDelta="100"
        android:toYDelta="0"
        android:repeatCount="-1"
        android:repeatMode="reverse"
         />

</set>

 ImageView ivTranslateXml = (ImageView) findViewById(R.id.iv_translate_xml);
AnimationSet translateSet  = (AnimationSet) AnimationUtils.loadAnimation(TweenActivity.this,R.anim.anim_tween_translate);
ivTranslateXml.startAnimation(translateSet);

Code

  ImageView ivTranslateCode = (ImageView) findViewById(R.id.iv_translate_code);
  TranslateAnimation translateAnimation = new TranslateAnimation( 0,100,0,0);
  translateAnimation.setDuration(1000);
  translateAnimation.setRepeatMode(Animation.REVERSE);
  translateAnimation.setRepeatCount(-1);
  ivTranslateCode.startAnimation(translateAnimation);

旋轉(zhuǎn)變化 Rotate

XML

anim_tween_rotate.xml

<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/accelerate_decelerate_interpolator">

<rotate
    android:duration="1000"
    android:fromDegrees="0"
    android:toDegrees="360"
    android:toXScale="1"
    android:toYScale="1"
    android:pivotX="50%"
    android:pivotY="50%"
    android:repeatCount="-1"
    android:repeatMode="reverse"
     />

</set>

ImageView ivRotateXml = (ImageView) findViewById(R.id.iv_rotate_xml);
AnimationSet rotateSet  = (AnimationSet) AnimationUtils.loadAnimati(TweenActivity.this,R.anim.anim_tween_rotate);
ivRotateXml.startAnimation(rotateSet);

Code

ImageView ivRotateCode = (ImageView) findViewById(R.id.iv_rotate_code);
RotateAnimation rotateAnimation = new RotateAnimation( 0,360, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
rotateAnimation.setDuration(1000);
rotateAnimation.setRepeatMode(Animation.REVERSE);
rotateAnimation.setRepeatCount(-1);
ivRotateCode.startAnimation(rotateAnimation);

組合起來

上面顯示的就是每一種效果各自實現(xiàn)的方法璃谨,現(xiàn)在我們可以讓這些效果組合起來。

xml

<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:interpolator="@android:anim/accelerate_decelerate_interpolator"
    >

    <alpha
        android:duration="1000"
        android:fromAlpha="0"
        android:repeatCount="-1"
        android:repeatMode="reverse"
        android:toAlpha="1" />

    <rotate
        android:duration="1000"
        android:fromDegrees="0"
        android:pivotX="50%"
        android:pivotY="50%"
        android:repeatCount="-1"
        android:repeatMode="reverse"
        android:toDegrees="360"
        android:toXScale="1"
        android:toYScale="1" />


    <scale
        android:duration="1000"
        android:fromXScale="0.2"
        android:fromYScale="0.2"
        android:pivotX="50%"
        android:pivotY="50%"
        android:repeatCount="-1"
        android:repeatMode="reverse"
        android:toXScale="1"
        android:toYScale="1" />

    <translate
        android:duration="1000"
        android:fromXDelta="0"
        android:fromYDelta="0"
        android:repeatCount="-1"
        android:repeatMode="reverse"
        android:toXDelta="100"
        android:toYDelta="0" />
</set>

ImageView ivTogetherXml = (ImageView) findViewById(R.id.iv_together_xml);
AnimationSet togetherSet  = (AnimationSet) AnimationUtils.loadAnimation(TweenActivity.this,R.anim.anim_tween_together);
ivTogetherXml.startAnimation(togetherSet);

Code

ImageView ivTogetherCode = (ImageView) findViewById(R.id.iv_together_code);
AnimationSet animationSet = new AnimationSet(false);
animationSet.addAnimation(alphaAnimation);
animationSet.addAnimation(rotateAnimation);
animationSet.addAnimation(translateAnimation);
animationSet.addAnimation(scaleAnimation);
ivTogetherCode.startAnimation(animationSet);

效果如圖所示:

監(jiān)聽

播放動畫效果的時候我們可以做到對動畫開始遣总、結(jié)束睬罗、重復(fù)的監(jiān)聽轨功。

alphaAnimation.setAnimationListener(new Animation.AnimationListener() {
        @Override
        public void onAnimationStart(Animation animation) {
            //動畫開始時調(diào)用
        }

        @Override
        public void onAnimationEnd(Animation animation) {
            //動畫結(jié)束時調(diào)用
        }

        @Override
        public void onAnimationRepeat(Animation animation) {
            //動畫重復(fù)時調(diào)用
        }
    });

只要在對應(yīng)的位置添加自己想要的效果,那么就可以實現(xiàn)了容达。

AccelerateInterpolator 加速古涧,開始時慢中間加速

幾種自帶的動畫插入器

DecelerateInterpolator 減速,開始時快然后減速

AccelerateDecelerateInterolator 先加速后減速花盐,開始結(jié)束時慢羡滑,中間加速

AnticipateInterpolator 反向,先向相反方向改變一段再加速播放

AnticipateOvershootInterpolator 反向加超越算芯,先向相反方向改變柒昏,再加速播放,會超出目的值然后緩慢移動至目的值

BounceInterpolator 跳躍熙揍,快到目的值時值會跳躍职祷,如目的值100,后面的值可能依次為85届囚,77有梆,70,80意系,90泥耀,100

CycleIinterpolator 循環(huán),動畫循環(huán)一定次數(shù)蛔添,值的改變?yōu)橐徽液瘮?shù):Math.sin(2* mCycles* Math.PI* input)

LinearInterpolator 線性痰催,線性均勻改變

OvershootInterpolator超越,最后超出目的值然后緩慢改變到目的值

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末迎瞧,一起剝皮案震驚了整個濱河市夸溶,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌夹攒,老刑警劉巖蜘醋,帶你破解...
    沈念sama閱讀 219,039評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異咏尝,居然都是意外死亡压语,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,426評論 3 395
  • 文/潘曉璐 我一進店門编检,熙熙樓的掌柜王于貴愁眉苦臉地迎上來胎食,“玉大人,你說我怎么就攤上這事允懂〔蘖” “怎么了?”我有些...
    開封第一講書人閱讀 165,417評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長粥航。 經(jīng)常有香客問我琅捏,道長,這世上最難降的妖魔是什么递雀? 我笑而不...
    開封第一講書人閱讀 58,868評論 1 295
  • 正文 為了忘掉前任柄延,我火速辦了婚禮,結(jié)果婚禮上缀程,老公的妹妹穿的比我還像新娘搜吧。我一直安慰自己,他們只是感情好杨凑,可當(dāng)我...
    茶點故事閱讀 67,892評論 6 392
  • 文/花漫 我一把揭開白布滤奈。 她就那樣靜靜地躺著,像睡著了一般撩满。 火紅的嫁衣襯著肌膚如雪蜒程。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,692評論 1 305
  • 那天伺帘,我揣著相機與錄音搞糕,去河邊找鬼。 笑死曼追,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的汉规。 我是一名探鬼主播礼殊,決...
    沈念sama閱讀 40,416評論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼针史!你這毒婦竟也來了晶伦?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,326評論 0 276
  • 序言:老撾萬榮一對情侶失蹤啄枕,失蹤者是張志新(化名)和其女友劉穎婚陪,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體频祝,經(jīng)...
    沈念sama閱讀 45,782評論 1 316
  • 正文 獨居荒郊野嶺守林人離奇死亡泌参,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,957評論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了常空。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片沽一。...
    茶點故事閱讀 40,102評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖漓糙,靈堂內(nèi)的尸體忽然破棺而出铣缠,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 35,790評論 5 346
  • 正文 年R本政府宣布蝗蛙,位于F島的核電站蝇庭,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏捡硅。R本人自食惡果不足惜哮内,卻給世界環(huán)境...
    茶點故事閱讀 41,442評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望病曾。 院中可真熱鬧牍蜂,春花似錦、人聲如沸泰涂。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,996評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽逼蒙。三九已至从绘,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間是牢,已是汗流浹背僵井。 一陣腳步聲響...
    開封第一講書人閱讀 33,113評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留驳棱,地道東北人亮隙。 一個月前我還...
    沈念sama閱讀 48,332評論 3 373
  • 正文 我出身青樓兄一,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子阅畴,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,044評論 2 355

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