Android寶典|動(dòng)畫(huà)必考知識(shí)點(diǎn)總結(jié)

目錄

  1. 思維導(dǎo)圖
  2. 幀動(dòng)畫(huà)
    • 使用方式
    • 優(yōu)缺點(diǎn)
    • 應(yīng)用場(chǎng)景
  3. 補(bǔ)間動(dòng)畫(huà)
    • 位移鹃觉、旋轉(zhuǎn)、縮放、透明度動(dòng)畫(huà)
    • 優(yōu)缺點(diǎn)
    • 應(yīng)用場(chǎng)景
  4. 屬性動(dòng)畫(huà)
    • 層次關(guān)系
    • ValueAnimator
      • ObjectAnimator
      • TimeAnimator
    • AnimatorSet
  5. 插值器、估值器
    • TypeEvaluator
      • IntEvaluator
      • FloutEvaluator
      • ArgbEvaluator
    • TimeInterpolator / Interpolator / BaseInterpolator
      • LinearInterpolator
      • AccelerateDecelerateInterpolator
  6. 參考

思維導(dǎo)圖

image

幀動(dòng)畫(huà)

使用方式
  1. xml 定義方式

    在 drawable 目錄下定義一個(gè) drawable-list闲擦,然后給圖片設(shè)置 res 就好了流济。

    <?xml version="1.0" encoding="utf-8"?>
    <animation-list xmlns:android="http://schemas.android.com/apk/res/android">
        <item android:drawable="@drawable/ic_vip" android:duration="100"/>
        <item android:drawable="@drawable/ic_account" android:duration="100"/>
        <item android:drawable="@drawable/ic_clouse" android:duration="100"/>
     //...
    </animation-list>
    
    mIvFrame.setImageResource(R.drawable.anim_frame);
    AnimationDrawable drawable = (AnimationDrawable) mIvFrame.getDrawable();
    drawable.start();
    drawable.stop();
    
  2. Java 代碼實(shí)現(xiàn)

    其實(shí)就是用代碼構(gòu)建 AnimationDrawable炭庙。

    mAnimationDrawable=new AnimationDrawable();
    for (int i = 0; i < 10; i++) {
        if (i<5){
        mAnimationDrawable.addFrame(getDrawable(R.drawable.ic_vip),100);
        }else {
           mAnimationDrawable.addFrame(getDrawable(R.drawable.ic_clouse),100);
        }
    }
    mIvFrame.setImageDrawable(mAnimationDrawable);
    mAnimationDrawable.start();
    mAnimationDrawable.stop();
    
優(yōu)缺點(diǎn)

優(yōu)點(diǎn):使用簡(jiǎn)單

缺點(diǎn):圖片是全部加載到內(nèi)存中先嬉,可能導(dǎo)致 OOM钻蔑。

應(yīng)用場(chǎng)景

基本上很少使用啥刻,可以看成 GIF 圖。

補(bǔ)間動(dòng)畫(huà)

位移動(dòng)畫(huà)
  1. xml 定義方式

    <?xml version="1.0" encoding="utf-8"?>
    <set xmlns:android="http://schemas.android.com/apk/res/android">
        <translate
            android:duration="1000"
            android:toXDelta="100"
            android:toYDelta="100"
            android:fromYDelta="0"
            android:fromXDelta="0"/>
    </set>
    
    mAnimation = AnimationUtils.loadAnimation(mContext, R.anim.anim_trans);
    mIvFrame.startAnimation(mAnimation);
    
  2. Java 代碼實(shí)現(xiàn)方式

    TranslateAnimation animation = new TranslateAnimation(0, 100, 0, 100);
    animation.setDuration(1000);
    animation.setFillAfter(true);
    mIvFrame.startAnimation(animation);
    
其他動(dòng)畫(huà)

類(lèi)似咪笑,不舉例了可帽。

優(yōu)缺點(diǎn)

優(yōu)點(diǎn):使用簡(jiǎn)單

缺點(diǎn):只改變顯示,不改變實(shí)際屬性

應(yīng)用場(chǎng)景

基本上大部分動(dòng)畫(huà)都能實(shí)現(xiàn)窗怒,常見(jiàn)于 Activity 轉(zhuǎn)場(chǎng)動(dòng)畫(huà)等等

屬性動(dòng)畫(huà)

層次關(guān)系

Animator

  • AnimatorSet
  • ValueAnimator
    • ObjectAnimator
    • TimeAnimator
ValueAnimator

常用使用方式:

    private void setAnimator() {
        mValueAnimator = new ValueAnimator();
        mValueAnimator.setIntValues(0, 500);
        mValueAnimator.setDuration(2000);
        mValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                Log.i(TAG, "onAnimationUpdate: " + animation.getAnimatedValue());
                float y = ((int) animation.getAnimatedValue()) * 1.0f;
                mIvFrame.setTranslationY(y);
            }
        });
        mValueAnimator.start();
    }
ObjectAnimator
        ObjectAnimator animator = ObjectAnimator
                .ofFloat(mBtnStart, "translationY", 0, 200)
                .setDuration(2000);
        animator.start();

ObjectAnimator 在每次更新的時(shí)候會(huì)自動(dòng)走 setXxx 方法映跟,所以就不需要像 ValueAnimator 一樣手動(dòng)添加監(jiān)聽(tīng)器,但是 ValueAnimator 的靈活性更好扬虚。

TimeAnimator

同樣是繼承至 ValueAnimator努隙,但是它只做一件事:提供一個(gè)時(shí)間流,每 18ms 回調(diào)一次辜昵。

        mTimeAnimator = new TimeAnimator();
        mTimeAnimator.setTimeListener(new TimeAnimator.TimeListener() {
            @Override
            public void onTimeUpdate(TimeAnimator animation, long totalTime, long deltaTime) {
                //動(dòng)畫(huà)執(zhí)行的總時(shí)間_動(dòng)畫(huà)從上一楨到當(dāng)前楨的間隔時(shí)間荸镊,單位都是毫秒
                Log.i(TAG, "onTimeUpdate: " + totalTime + "   " + deltaTime);
            }
        });

運(yùn)行結(jié)果:

2018-12-30 09:01:54.344 6656-6656/com.example.omooo.demoproject I/AnimatorActivity: onTimeUpdate: 0   0
2018-12-30 09:01:54.346 6656-6656/com.example.omooo.demoproject I/AnimatorActivity: onTimeUpdate: 0   0
2018-12-30 09:01:54.356 6656-6656/com.example.omooo.demoproject I/AnimatorActivity: onTimeUpdate: 7   7
2018-12-30 09:01:54.375 6656-6656/com.example.omooo.demoproject I/AnimatorActivity: onTimeUpdate: 24   17
2018-12-30 09:01:54.388 6656-6656/com.example.omooo.demoproject I/AnimatorActivity: onTimeUpdate: 42   18
2018-12-30 09:01:54.407 6656-6656/com.example.omooo.demoproject I/AnimatorActivity: onTimeUpdate: 60   18
2018-12-30 09:01:54.424 6656-6656/com.example.omooo.demoproject I/AnimatorActivity: onTimeUpdate: 78   18
2018-12-30 09:01:54.444 6656-6656/com.example.omooo.demoproject I/AnimatorActivity: onTimeUpdate: 96   18

估值器、插值器

估值器表示屬性的從初始值過(guò)渡到結(jié)束值變化的具體數(shù)值堪置,而插值器則表示變化率躬存,比如先加速后減速(默認(rèn))、勻速等等舀锨。

估值器

估值器都需要實(shí)現(xiàn) TypeEvaluator 接口:

public interface TypeEvaluator<T> {
    public T evaluate(float fraction, T startValue, T endValue);
}

其實(shí)就是根據(jù)初始值和結(jié)束值算出一個(gè)值岭洲。

系統(tǒng)已經(jīng)有幾個(gè)默認(rèn)實(shí)現(xiàn),比如 ArgbEvaluator坎匿、IntEvaluator盾剩、FloatEvaluator 等等。其實(shí)我們?cè)谟?ValueAnimator.ofArgb() 的時(shí)候替蔬,內(nèi)部就是用 ArgbEvaluator 實(shí)現(xiàn)的告私,那對(duì)于 ValueAnimator.ofInt()、ValueAnimator.ofFloat() 方法是不是也是一樣的道理呢承桥?

下面將介紹如何自定義估值器驻粟,所實(shí)現(xiàn)的功能:

image

首先定義按鈕所需要的屬性:

public class ButtonInfo {
    public int color;
    public int x;
    public int y;

    public ButtonInfo(int color, int x, int y) {
        this.color = color;
        this.x = x;
        this.y = y;
    }

    public ButtonInfo() {
    }
}

自定義估值器:

public class ButtonEvaluator implements TypeEvaluator {

    @Override
    public Object evaluate(float fraction, Object startValue, Object endValue) {
        ButtonInfo start = (ButtonInfo) startValue;
        ButtonInfo end = (ButtonInfo) endValue;
        ButtonInfo buttonInfo = new ButtonInfo();
        ArgbEvaluator argbEvaluator = new ArgbEvaluator();
        buttonInfo.color = (int) argbEvaluator.evaluate(fraction, ((ButtonInfo) startValue).color, ((ButtonInfo) endValue).color);
        buttonInfo.x = (int) (fraction * (end.x - start.x) + start.x);
        buttonInfo.y = (int) (fraction * (end.y - start.y) + start.y);
        return buttonInfo;
    }
}

運(yùn)用:

    private void setTransAnimator() {
        mValueAnimator = ValueAnimator.ofObject(new ButtonEvaluator(), new ButtonInfo(0xff94E1F7, 0, 0)
                , new ButtonInfo(0xffF35519, 500, 500));
        mValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                ButtonInfo buttonInfo = (ButtonInfo) animation.getAnimatedValue();
                mBtnStart.setBackgroundColor(buttonInfo.color);
                mBtnStart.setTranslationX(buttonInfo.x);
                mBtnStart.setTranslationY(buttonInfo.y);
            }
        });
        mValueAnimator.setDuration(5000);
        mValueAnimator.start();
    }

可以,看出快毛,實(shí)際上自定義估值器還是很簡(jiǎn)單格嗅。

插值器

插值器需要實(shí)現(xiàn) TimeInterpolator 或 Interpolator:

public interface TimeInterpolator {
    float getInterpolation(float input);
}

public interface Interpolator extends TimeInterpolator {
    
}

Android 系統(tǒng)內(nèi)置了幾種實(shí)現(xiàn),默認(rèn)是先加速后減速唠帝,即 AccelerateDecelerateInterpolator 屯掖,看一下源碼實(shí)現(xiàn):

public class AccelerateDecelerateInterpolator extends BaseInterpolator
        implements NativeInterpolatorFactory {
    public float getInterpolation(float input) {
        return (float)(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f;
    }
    //...
}

四五十行代碼,首先明確的就是 value 值是 0 ~ 1襟衰,所以以上就是表示余旋函數(shù)在 pi/2 和 pi 之間贴铜,就是先加速后減速。

那我們?cè)诳匆幌?LinearInterpolator 的源碼:

/**
 * An interpolator where the rate of change is constant
 */
@HasNativeInterpolator
public class LinearInterpolator extends BaseInterpolator implements NativeInterpolatorFactory {
    public float getInterpolation(float input) {
        return input;
    }
    //...
}

那在自定義插值器就易如反掌了呀瀑晒,定義一個(gè)先減速后加速的插值器绍坝,如下:

public class DeceAcceInterpolator implements TimeInterpolator {
    @Override
    public float getInterpolation(float input) {
        //余旋函數(shù) 0 ~ PI/2
        return (float) Math.cos(input * Math.PI / 2);
    }
}

然后給 ValueAnimator 設(shè)置自定義的插值器:

mValueAnimator.setInterpolator(new DeceAcceInterpolator());
image

啊苔悦?怎么反向了轩褐?看來(lái)設(shè)置變化率需要在 x 軸的下方呀。至于為什么玖详?留個(gè)坑把介。

參考

Android 動(dòng)畫(huà) Animator 家族使用指南

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市蟋座,隨后出現(xiàn)的幾起案子拗踢,更是在濱河造成了極大的恐慌,老刑警劉巖向臀,帶你破解...
    沈念sama閱讀 212,542評(píng)論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件巢墅,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡券膀,警方通過(guò)查閱死者的電腦和手機(jī)君纫,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,596評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)三娩,“玉大人庵芭,你說(shuō)我怎么就攤上這事∪讣啵” “怎么了双吆?”我有些...
    開(kāi)封第一講書(shū)人閱讀 158,021評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)会前。 經(jīng)常有香客問(wèn)我好乐,道長(zhǎng),這世上最難降的妖魔是什么瓦宜? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,682評(píng)論 1 284
  • 正文 為了忘掉前任蔚万,我火速辦了婚禮,結(jié)果婚禮上临庇,老公的妹妹穿的比我還像新娘反璃。我一直安慰自己昵慌,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,792評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布淮蜈。 她就那樣靜靜地躺著斋攀,像睡著了一般。 火紅的嫁衣襯著肌膚如雪梧田。 梳的紋絲不亂的頭發(fā)上淳蔼,一...
    開(kāi)封第一講書(shū)人閱讀 49,985評(píng)論 1 291
  • 那天,我揣著相機(jī)與錄音裁眯,去河邊找鬼鹉梨。 笑死,一個(gè)胖子當(dāng)著我的面吹牛穿稳,可吹牛的內(nèi)容都是我干的存皂。 我是一名探鬼主播,決...
    沈念sama閱讀 39,107評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼司草,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼艰垂!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起埋虹,我...
    開(kāi)封第一講書(shū)人閱讀 37,845評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤猜憎,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后搔课,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體胰柑,經(jīng)...
    沈念sama閱讀 44,299評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,612評(píng)論 2 327
  • 正文 我和宋清朗相戀三年爬泥,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了柬讨。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,747評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡袍啡,死狀恐怖踩官,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情境输,我是刑警寧澤蔗牡,帶...
    沈念sama閱讀 34,441評(píng)論 4 333
  • 正文 年R本政府宣布,位于F島的核電站嗅剖,受9級(jí)特大地震影響辩越,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜信粮,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,072評(píng)論 3 317
  • 文/蒙蒙 一黔攒、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦督惰、人聲如沸不傅。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,828評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)蛤签。三九已至,卻和暖如春栅哀,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背称龙。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,069評(píng)論 1 267
  • 我被黑心中介騙來(lái)泰國(guó)打工留拾, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人鲫尊。 一個(gè)月前我還...
    沈念sama閱讀 46,545評(píng)論 2 362
  • 正文 我出身青樓痴柔,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親疫向。 傳聞我的和親對(duì)象是個(gè)殘疾皇子咳蔚,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,658評(píng)論 2 350

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