Android動畫:手把手帶你深入了解神秘的插值器(Interpolator)


前言

  • 動畫的使用 是 Android 開發(fā)中常用的知識
  • 可是動畫的種類繁多、使用復(fù)雜晰甚,每當(dāng)需要 采用自定義動畫 實現(xiàn) 復(fù)雜的動畫效果時,很多開發(fā)者就顯得束手無策
  • Android中 補間動畫 & 屬性動畫實現(xiàn)動畫的原理是:
實現(xiàn)原理

其中,步驟2中的 插值器(Interpolator)和估值器(TypeEvaluator)是實現(xiàn) 復(fù)雜動畫效果的關(guān)鍵;本文主要講解 將詳細講解 插值器(Interpolator)金踪,通過閱讀本文你將能輕松實現(xiàn)復(fù)雜的動畫效果

Carson帶你學(xué)Android動畫系列文章:
Carson帶你學(xué)Android:一份全面&詳細的動畫知識學(xué)習(xí)攻略
Carson帶你學(xué)Android:常見的三種動畫類型
Carson帶你學(xué)Android:補間動畫學(xué)習(xí)教程
Carson帶你學(xué)Android:屬性動畫學(xué)習(xí)教程
Carson帶你學(xué)Android:逐幀動畫學(xué)習(xí)教程
Carson帶你學(xué)Android:自定義動畫神器-估值器(含實例教學(xué))
Carson帶你學(xué)Android:自定義動畫神器-插值器(含實例教學(xué))


目錄

示意圖

1. 簡介

  • 定義:Android實現(xiàn)動畫效果中的一個輔助接口
  • 作用:設(shè)置 屬性值 從初始值過渡到結(jié)束值 的變化規(guī)律
  1. 如勻速、加速 & 減速 等等
  2. 即確定了 動畫效果變化的模式牵敷,如勻速變化胡岔、加速變化 等等

2. 應(yīng)用場景

實現(xiàn)非線性運動的動畫效果。非線性運動是指動畫改變的速率不是一成不變的劣领,如加速姐军、減速運動的動畫效果铁材。


3. 具體使用

插值器在動畫的使用有兩種方式:在XML / Java代碼中設(shè)置:

/*
 * 使用方式1:xml
 * 主要是設(shè)置插值器屬性 android:interpolator
 */
 <?xml version="1.0" encoding="utf-8"?>
    <scale xmlns:android="http://schemas.android.com/apk/res/android"

        // 通過資源ID設(shè)置插值器
        android:interpolator="@android:anim/overshoot_interpolator"
        android:duration="3000"
        android:fromXScale="0.0"
        android:fromYScale="0.0"
        android:pivotX="50%"
        android:pivotY="50%"
        android:toXScale="2"
        android:toYScale="2" />
 >

/*
 * 使用方式2:java
 */
// 步驟1:創(chuàng)建 需要設(shè)置動畫的 視圖View
Button mButton = (Button) findViewById(R.id.Button);
// 步驟2:創(chuàng)建透明度動畫的對象 & 設(shè)置動畫效果
Animation alphaAnimation = new AlphaAnimation(1,0);
// 步驟3:創(chuàng)建對應(yīng)的插值器類對象
alphaAnimation.setDuration(3000);
Interpolator overshootInterpolator = new OvershootInterpolator();
// 步驟4:給動畫設(shè)置插值器
alphaAnimation.setInterpolator(overshootInterpolator);
// 步驟5:播放動畫
mButton.startAnimation(alphaAnimation);
  • 那么使用插值器時的資源ID是什么呢尖淘?即有哪些類型的插值器可供我們使用呢?
  • 插值器分為兩種:Android內(nèi)置默認 & 自定義著觉,下面我將詳細介紹

4. 系統(tǒng)內(nèi)置插值器

4.1 類型

Android內(nèi)置了 9 種內(nèi)置的插值器實現(xiàn):

示意圖

4.2 具體使用

  • 當(dāng)在XML文件設(shè)置插值器時村生,只需傳入對應(yīng)的插值器資源ID即可
  • 當(dāng)在Java代碼設(shè)置插值器時,只需創(chuàng)建對應(yīng)的插值器對象即可

系統(tǒng)默認的插值器是AccelerateDecelerateInterpolator饼丘,即先加速后減速

4.3 效果圖

效果圖
  • 使用Android內(nèi)置的插值器能滿足大多數(shù)的動畫需求
  • 如果上述9個插值器無法滿足需求趁桃,還可以自定義插值器
  • 下面將介紹如何自定義插值器(Interpolator

5. 自定義插值器

5.1 本質(zhì)

根據(jù)動畫的進度(0%-100%)計算出當(dāng)前屬性值改變的百分比

5.2 實現(xiàn)方式

自定義插值器需要實現(xiàn)Interpolator或TimeInterpolator接口,并復(fù)寫getInterpolation()方法

  1. 補間動畫 實現(xiàn) Interpolator接口;屬性動畫實現(xiàn)TimeInterpolator接口
  2. TimeInterpolator接口是屬性動畫中新增的卫病,用于兼容Interpolator接口油啤,這使得所有過去的Interpolator實現(xiàn)類都可以直接在屬性動畫使用

Interpolator接口和TimeInterpolator接口說明如下:

// Interpolator接口
public interface Interpolator {  

    // 內(nèi)部只有一個方法:getInterpolation()
     float getInterpolation(float input) {  
        // 參數(shù)說明
        // input值值變化范圍是0-1,且隨著動畫進度(0% - 100% )均勻變化
        // 即動畫開始時蟀苛,input值 = 0益咬;動畫結(jié)束時input = 1
        // 而中間的值則是隨著動畫的進度(0% - 100%)在0到1之間均勻增加
        
      ...// 插值器的計算邏輯

      return xxx;
      // 返回的值就是用于估值器繼續(xù)計算的fraction值帜平,下面會詳細說明
    }  

// TimeInterpolator接口
// 同上
public interface TimeInterpolator {  
  
    float getInterpolation(float input){
         ...
    };  
}  

從上面可以看出幽告,自定義插值器的關(guān)鍵在于:對input值根據(jù)動畫的進度(0%-100%)通過邏輯計算從而計算出當(dāng)前屬性值改變的百分比。先來看兩個已經(jīng)實現(xiàn)好的系統(tǒng)內(nèi)置差值器:

  • 勻速插值器:LinearInterpolator
  • 先加速再減速 插值器:AccelerateDecelerateInterpolator
/*
 * 勻速差值器:LinearInterpolator
 */
@HasNativeInterpolator  
public class LinearInterpolator extends BaseInterpolator implements NativeInterpolatorFactory {  
   
    ... // 僅貼出關(guān)鍵代碼

    public float getInterpolation(float input) {  
        return input;  
        // 沒有對input值進行任何邏輯處理裆甩,直接返回
        // 即input值 = fraction值
        // 因為input值是勻速增加的冗锁,因此fraction值也是勻速增加的,所以動畫的運動情況也是勻速的嗤栓,所以是勻速插值器
    }  

/*
 * 先加速再減速 差值器:AccelerateDecelerateInterpolator
 */
@HasNativeInterpolator  
public class AccelerateDecelerateInterpolator implements Interpolator, NativeInterpolatorFactory {  
      
    ... // 僅貼出關(guān)鍵代碼
    
    public float getInterpolation(float input) {  
        return (float)(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f;
        // input的運算邏輯如下:
        // 使用了余弦函數(shù)冻河,因input的取值范圍是0到1,那么cos函數(shù)中的取值范圍就是π到2π茉帅。
        // 而cos(π)的結(jié)果是-1芋绸,cos(2π)的結(jié)果是1
        // 所以該值除以2加上0.5后担敌,getInterpolation()方法最終返回的結(jié)果值還是在0到1之間。只不過經(jīng)過了余弦運算之后马昙,最終的結(jié)果不再是勻速增加的了,而是經(jīng)歷了一個先加速后減速的過程
        // 所以最終刹悴,fraction值 = 運算后的值 = 先加速后減速
        // 所以該差值器是先加速再減速的
    }  
}

5.3 實例說明

下面,我將寫一個自定義Interpolator:先減速后加速子房。

/*
 * 步驟1:根據(jù)需求實現(xiàn)Interpolator接口
 * DecelerateAccelerateInterpolator.java
 */
public class DecelerateAccelerateInterpolator implements TimeInterpolator {
    
    @Override
    public float getInterpolation(float input) {
        float result;
        if (input <= 0.5) {
            result = (float) (Math.sin(Math.PI * input)) / 2;
            // 使用正弦函數(shù)來實現(xiàn)先減速后加速的功能,邏輯如下:
            // 因為正弦函數(shù)初始弧度變化值非常大就轧,剛好和余弦函數(shù)是相反的
            // 隨著弧度的增加证杭,正弦函數(shù)的變化值也會逐漸變小解愤,這樣也就實現(xiàn)了減速的效果送讲。
            // 當(dāng)弧度大于π/2之后,整個過程相反了過來哼鬓,現(xiàn)在正弦函數(shù)的弧度變化值非常小异希,漸漸隨著弧度繼續(xù)增加宠互,變化值越來越大,弧度到π時結(jié)束搏色,這樣從0過度到π频轿,也就實現(xiàn)了先減速后加速的效果
        } else {
            result = (float) (2 - Math.sin(Math.PI * input)) / 2;
        }
        return result;
        // 返回的result值 = 隨著動畫進度呈先減速后加速的變化趨勢
    }
}

/*
 * 步驟2:設(shè)置使用
 * MainActivity.java
 */
 // 1. 創(chuàng)建動畫作用對象:此處以Button為例
 mButton = (Button) findViewById(R.id.Button);

 // 2. 獲得當(dāng)前按鈕的位置
float curTranslationX = mButton.getTranslationX();

// 3. 創(chuàng)建動畫對象 & 設(shè)置動畫
ObjectAnimator animator = ObjectAnimator.ofFloat(mButton, "translationX", curTranslationX, 300,curTranslationX);
// 表示的是:
// 動畫作用對象是mButton
// 動畫作用的對象的屬性是X軸平移
// 動畫效果是:從當(dāng)前位置平移到 x=1500 再平移到初始位置

// 4. 設(shè)置步驟1中設(shè)置好的插值器:先減速后加速
animator.setInterpolator(new DecelerateAccelerateInterpolator());

// 5. 啟動動畫
animator.start();

效果圖

差值器.gif

6. 與估值器的區(qū)別

估值器和插值器很多人容易混淆航邢,具體區(qū)別如下:

示意圖

7. 總結(jié)


歡迎關(guān)注Carson_Ho的簡書

不定期分享關(guān)于安卓開發(fā)的干貨薄榛,追求短勒极、平辱匿、快炫彩,但卻不缺深度媒楼。


請點贊划址!因為你的鼓勵是我寫作的最大動力夺颤!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末世澜,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子嵌洼,更是在濱河造成了極大的恐慌麻养,老刑警劉巖诺舔,帶你破解...
    沈念sama閱讀 206,839評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件许昨,死亡現(xiàn)場離奇詭異褥赊,居然都是意外死亡拌喉,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來残家,“玉大人坞淮,你說我怎么就攤上這事回窘。” “怎么了烁涌?”我有些...
    開封第一講書人閱讀 153,116評論 0 344
  • 文/不壞的土叔 我叫張陵撮执,是天一觀的道長抒钱。 經(jīng)常有香客問我,道長仗扬,這世上最難降的妖魔是什么蕾额? 我笑而不...
    開封第一講書人閱讀 55,371評論 1 279
  • 正文 為了忘掉前任逼友,我火速辦了婚禮秤涩,結(jié)果婚禮上筐眷,老公的妹妹穿的比我還像新娘。我一直安慰自己照棋,他們只是感情好烈炭,可當(dāng)我...
    茶點故事閱讀 64,384評論 5 374
  • 文/花漫 我一把揭開白布符隙。 她就那樣靜靜地躺著垫毙,像睡著了一般综芥。 火紅的嫁衣襯著肌膚如雪膀藐。 梳的紋絲不亂的頭發(fā)上红省,一...
    開封第一講書人閱讀 49,111評論 1 285
  • 那天类腮,我揣著相機與錄音,去河邊找鬼针饥。 笑死需频,一個胖子當(dāng)著我的面吹牛昭殉,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播蹂风,決...
    沈念sama閱讀 38,416評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼惠啄,長吁一口氣:“原來是場噩夢啊……” “哼撵渡!你這毒婦竟也來了趋距?” 一聲冷哼從身側(cè)響起越除,我...
    開封第一講書人閱讀 37,053評論 0 259
  • 序言:老撾萬榮一對情侶失蹤廊敌,失蹤者是張志新(化名)和其女友劉穎骡澈,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體囤锉,經(jīng)...
    沈念sama閱讀 43,558評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡官地,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,007評論 2 325
  • 正文 我和宋清朗相戀三年赤炒,在試婚紗的時候發(fā)現(xiàn)自己被綠了亏较。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片雪情。...
    茶點故事閱讀 38,117評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡巡通,死狀恐怖宴凉,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情炉旷,我是刑警寧澤叉讥,帶...
    沈念sama閱讀 33,756評論 4 324
  • 正文 年R本政府宣布罐盔,位于F島的核電站救崔,受9級特大地震影響六孵,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜本今,卻給世界環(huán)境...
    茶點故事閱讀 39,324評論 3 307
  • 文/蒙蒙 一冠息、第九天 我趴在偏房一處隱蔽的房頂上張望逛艰。 院中可真熱鬧,春花似錦菇绵、人聲如沸脸甘。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽硝桩。三九已至碗脊,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間祈坠,已是汗流浹背赦拘。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評論 1 262
  • 我被黑心中介騙來泰國打工躺同, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留丸逸,地道東北人黄刚。 一個月前我還...
    沈念sama閱讀 45,578評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像研铆,于是被迫代替她去往敵國和親州叠。 傳聞我的和親對象是個殘疾皇子咧栗,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,877評論 2 345

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