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

實現(xiàn)原理
其中,步驟2中的 插值器(Interpolator)和估值器(TypeEvaluator)是實現(xiàn) 復雜動畫效果的關鍵
本文主要講解 將詳細講解 插值器(Interpolator),通過閱讀本文你將能輕松實現(xiàn)復雜的動畫效果
關于Android動畫的系列文章
動畫的使用,請參考文章:
Android 屬性動畫:這是一篇很詳細的 屬性動畫 總結(jié)&攻略
Android 逐幀動畫:關于 逐幀動畫 的使用都在這里了!
Android 動畫:你真的會使用插值器與估值器嗎?(含詳細實例教學)
自定義View的原理,請參考文章:
(1)自定義View基礎 - 最易懂的自定義View原理系列
(2)自定義View Measure過程 - 最易懂的自定義View原理系列
(3)自定義View Layout過程 - 最易懂的自定義View原理系列
(4)自定義View Draw過程- 最易懂的自定義View原理系列
自定義View的應用,請參考文章:
為什么你的自定義View wrap_content不起作用?
目錄

示意圖
1. 簡介
定義:Android實現(xiàn)動畫效果中的一個輔助接口
作用:設置 屬性值 從初始值過渡到結(jié)束值 的變化規(guī)律
如勻速、加速 & 減速 等等
即確定了 動畫效果變化的模式,如勻速變化、加速變化 等等
2. 應用場景
實現(xiàn)非線性運動的動畫效果
非線性運動:動畫改變的速率不是一成不變的,如加速 & 減速運動都屬于非線性運動
3. 具體使用
插值器在動畫的使用有兩種方式:在XML / Java代碼中設置:
3.1 XML設置
主要是設置插值器屬性android:interpolator
<?xml version="1.0" encoding="utf-8"?>>
3.2 Java設置
Button mButton=(Button)findViewById(R.id.Button);// 步驟1:創(chuàng)建 需要設置動畫的 視圖ViewAnimation alphaAnimation=newAlphaAnimation(1,0);// 步驟2:創(chuàng)建透明度動畫的對象 & 設置動畫效果alphaAnimation.setDuration(3000);Interpolator overshootInterpolator=newOvershootInterpolator();// 步驟3:創(chuàng)建對應的插值器類對象alphaAnimation.setInterpolator(overshootInterpolator);// 步驟4:給動畫設置插值器mButton.startAnimation(alphaAnimation);// 步驟5:播放動畫
那么使用插值器時的資源ID是什么呢?即有哪些類型的插值器可供我們使用呢?
插值器分為兩種:Android內(nèi)置默認 & 自定義,下面我將詳細介紹
4. 系統(tǒng)內(nèi)置插值器
4.1 類型
Android內(nèi)置了 9 種內(nèi)置的插值器實現(xiàn):

示意圖
4.2 具體使用
當在XML文件設置插值器時,只需傳入對應的插值器資源ID即可
當在Java代碼設置插值器時,只需創(chuàng)建對應的插值器對象即可
系統(tǒng)默認的插值器是AccelerateDecelerateInterpolator,即先加速后減速
4.3 效果圖

效果圖
使用Android內(nèi)置的插值器能滿足大多數(shù)的動畫需求
如果上述9個插值器無法滿足需求,還可以自定義插值器
下面將介紹如何自定義插值器(Interpolator)
5. 自定義插值器
5.1 本質(zhì)
根據(jù)動畫的進度(0%-100%)計算出當前屬性值改變的百分比
5.2 實現(xiàn)方式
自定義插值器需要實現(xiàn)Interpolator/TimeInterpolator接口 & 復寫getInterpolation()
補間動畫 實現(xiàn)Interpolator接口;屬性動畫實現(xiàn)TimeInterpolator接口
TimeInterpolator接口是屬性動畫中新增的,用于兼容Interpolator接口,這使得所有過去的Interpolator實現(xiàn)類都可以直接在屬性動畫使用
// Interpolator接口publicinterfaceInterpolator{// 內(nèi)部只有一個方法floatgetInterpolation(floatinput){// 參數(shù)說明// input值值變化范圍是0-1,且隨著動畫進度(0% - 100% )均勻變化// 即動畫開始時,input值 = 0;動畫結(jié)束時input = 1// 而中間的值則是隨著動畫的進度(0% - 100%)在0到1之間均勻增加...// 插值器的計算邏輯returnxxx;// 返回的值就是用于估值器繼續(xù)計算的fraction值,下面會詳細說明}// TimeInterpolator接口// 同上publicinterfaceTimeInterpolator{floatgetInterpolation(floatinput);}
在學習自定義插值器前,我們先來看兩個已經(jīng)實現(xiàn)好的系統(tǒng)內(nèi)置差值器:
勻速插值器:LinearInterpolator
先加速再減速 插值器:AccelerateDecelerateInterpolator
// 勻速差值器:LinearInterpolator@HasNativeInterpolatorpublicclassLinearInterpolatorextendsBaseInterpolatorimplementsNativeInterpolatorFactory{// 僅貼出關鍵代碼...publicfloatgetInterpolation(floatinput){returninput;// 沒有對input值進行任何邏輯處理,直接返回// 即input值 = fraction值// 因為input值是勻速增加的,因此fraction值也是勻速增加的,所以動畫的運動情況也是勻速的,所以是勻速插值器}// 先加速再減速 差值器:AccelerateDecelerateInterpolator@HasNativeInterpolatorpublicclassAccelerateDecelerateInterpolatorimplementsInterpolator,NativeInterpolatorFactory{// 僅貼出關鍵代碼...publicfloatgetInterpolation(floatinput){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值 = 運算后的值 = 先加速后減速// 所以該差值器是先加速再減速的}}
從上面看出,自定義插值器的關鍵在于:對input值 根據(jù)動畫的進度(0%-100%)通過邏輯計算 計算出當前屬性值改變的百分比
下面我將用一個實例來說明該如何自定義插值器
5.3 實例說明
下面,我將寫一個自定義Interpolator:先減速后加速。
步驟1:根據(jù)需求實現(xiàn)Interpolator接口
DecelerateAccelerateInterpolator.java
publicclassDecelerateAccelerateInterpolatorimplementsTimeInterpolator{@OverridepublicfloatgetInterpolation(floatinput){floatresult;if(input<=0.5){result=(float)(Math.sin(Math.PI*input))/2;// 使用正弦函數(shù)來實現(xiàn)先減速后加速的功能,邏輯如下:// 因為正弦函數(shù)初始弧度變化值非常大,剛好和余弦函數(shù)是相反的// 隨著弧度的增加,正弦函數(shù)的變化值也會逐漸變小,這樣也就實現(xiàn)了減速的效果。// 當弧度大于π/2之后,整個過程相反了過來,現(xiàn)在正弦函數(shù)的弧度變化值非常小,漸漸隨著弧度繼續(xù)增加,變化值越來越大,弧度到π時結(jié)束,這樣從0過度到π,也就實現(xiàn)了先減速后加速的效果}else{result=(float)(2-Math.sin(Math.PI*input))/2;}returnresult;// 返回的result值 = 隨著動畫進度呈先減速后加速的變化趨勢}}
步驟2:設置使用
MainActivity.java
mButton=(Button)findViewById(R.id.Button);// 創(chuàng)建動畫作用對象:此處以Button為例floatcurTranslationX=mButton.getTranslationX();// 獲得當前按鈕的位置ObjectAnimator animator=ObjectAnimator.ofFloat(mButton,"translationX",curTranslationX,300,curTranslationX);// 創(chuàng)建動畫對象 & 設置動畫// 表示的是:// 動畫作用對象是mButton// 動畫作用的對象的屬性是X軸平移// 動畫效果是:從當前位置平移到 x=1500 再平移到初始位置animator.setDuration(5000);animator.setInterpolator(newDecelerateAccelerateInterpolator());// 設置插值器animator.start();// 啟動動畫
效果圖

差值器.gif
6. 與估值器的區(qū)別
估值器和插值器很多人容易混淆,具體區(qū)別如下:

示意圖
7. 總結(jié)
本文對Android動畫中的插值器進行了詳細分析,相信通過本文你已經(jīng)能實現(xiàn)復雜的動畫效果
關于Android動畫的系列文章
動畫的使用,請參考文章:
Android 屬性動畫:這是一篇很詳細的 屬性動畫 總結(jié)&攻略
Android 逐幀動畫:關于 逐幀動畫 的使用都在這里了!
Android 動畫:你真的會使用插值器與估值器嗎?(含詳細實例教學)
自定義View的原理,請參考文章:
(1)自定義View基礎 - 最易懂的自定義View原理系列
(2)自定義View Measure過程 - 最易懂的自定義View原理系列
(3)自定義View Layout過程 - 最易懂的自定義View原理系列
(4)自定義View Draw過程- 最易懂的自定義View原理系列
自定義View的應用,請參考文章:
為什么你的自定義View wrap_content不起作用?
接下來,我我將繼續(xù)對Android動畫進行分析,感興趣的同學可以繼續(xù)關注本人運營的Wechat Public Account:
我想給你們介紹一個與眾不同的Android微信公眾號(福利回贈)
作者:Carson_Ho
鏈接:http://www.itdecent.cn/p/2f19fe1e3ca1
來源:簡書
著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請注明出處。