深入理解 Android 動畫 Interpolator 類的使用
做過android動畫的人對Interpolator應該不會陌生,這個類主要是用來控制android動畫的執行速率,一般情況下,如果我們不設定,動畫都不是勻速執行的,系統預設是先加速後減速這樣一種動畫執行速率。
android通過Interpolator類來讓我們自己控制動畫的執行速率,還記得上一篇部落格中我們使用屬性動畫實現的旋轉效果嗎?在不設定Interpolator的情況下,這個動畫是先加速後減速,我們現在使用android系統提供的類LinearInterpolator來設定動畫的執行速率,LinearInterpolator可以讓這個動畫勻速執行,我們來看一個案例,我們有兩個TextView重疊放在一起,點選旋轉按鈕後這兩個TextView同時執行旋轉動畫,不同的是一個設定了LinearInterpolator,而另外一個什麼都沒有設定,程式碼如下:
LinearInterpolator ll = new LinearInterpolator(); ObjectAnimator animator = ObjectAnimator.ofFloat(tv, "rotation", 0f, 360f); animator.setInterpolator(ll); animator.setDuration(5000); animator.start(); ObjectAnimator animator2 = ObjectAnimator.ofFloat(tv2, "rotation", 0f, 360f); animator2.setDuration(5000); animator2.start();
效果圖如下:
現在我們可以很清楚的看到這裡的差異,一個TextView先加速後減速,一個一直勻速運動。
這就引起了我的好奇,究竟LinearInterpolator做了什麼,改變了動畫的執行速率。這裡我們就要看看原始碼了。
當我們呼叫animator.setInterpolator(ll);
的時候,呼叫的是ValueAnimator方法中的setInterpolator方法,原始碼如下:
public void setInterpolator(TimeInterpolator value) { if (value != null) { mInterpolator = value; } else { mInterpolator = new LinearInterpolator(); } }
我們看到這裡有一個mInterpolator變數,如果我們不執行這個方法,那麼mInterpolator 的預設值是多少呢?
我們找到了這樣兩行程式碼:
// The time interpolator to be used if none is set on the animation private static final TimeInterpolator sDefaultInterpolator = new AccelerateDecelerateInterpolator(); private TimeInterpolator mInterpolator = sDefaultInterpolator;
這下明朗了,如果我們不設定,那麼系統預設使用AccelerateDecelerateInterpolator,AccelerateDecelerateInterpolator又是什麼呢?繼續看原始碼:
public class AccelerateDecelerateInterpolator extends BaseInterpolator implements NativeInterpolatorFactory { public AccelerateDecelerateInterpolator() { } @SuppressWarnings({"UnusedDeclaration"}) public AccelerateDecelerateInterpolator(Context context, AttributeSet attrs) { } public float getInterpolation(float input) { return (float)(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f; } /** @hide */ @Override public long createNativeInterpolator() { return NativeInterpolatorFactoryHelper.createAccelerateDecelerateInterpolator(); } }
這裡的一個核心函式就是getInterpolation,使用了反餘弦函式,input傳入的值在0-1之間,因此這裡返回值的變化速率就是先增加後減少,對應的動畫執行速率就是先增加後減速。有興趣的童鞋可以使用MatLab來畫一下這個函式的影像。而當我們實現了LinearInterpolator之後,情況發生了變化:
public class LinearInterpolator extends BaseInterpolator implements NativeInterpolatorFactory { public LinearInterpolator() { } public LinearInterpolator(Context context, AttributeSet attrs) { } public float getInterpolation(float input) { return input; } /** @hide */ @Override public long createNativeInterpolator() { return NativeInterpolatorFactoryHelper.createLinearInterpolator(); } }
這裡乾淨利落直接返回了input,沒有經過任何計算。input返回的值是均勻的,因此動畫得以勻速執行。
看到這裡,大家應該就明白了,如果我們想要控制動畫的執行速率,應該重寫getInterpolation方法就能實現。為了證實我們的猜想,我們繼續看原始碼。
大部分時候,我們使用的系統提供的各種各樣的**Interpolator,比如上文說的LinearInterpolator,這些類都是繼承自Interpolator,而Interpolator則實現了TimeInterpolator介面,我們來看看一個繼承結構圖:
那麼這個終極大Boss TimeInterpolator究竟是什麼樣子呢?
package android.animation; /** * A time interpolator defines the rate of change of an animation. This allows animations * to have non-linear motion, such as acceleration and deceleration. */ 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); }
原始碼還是很簡單的,只有一個方法,就是getInterpolation,看來沒錯,就是它了,如果我們想要自定義Interpolator,只需要實現TimeInterpolator介面的getInterpolation方法就可以了,getInterpolation方法接收的引數是動畫執行的百分比,這個值是均勻的。
我們來個簡單的案例:
public class TanInterpolator implements TimeInterpolator { @Override public float getInterpolation(float t) { return (float) Math.sin((t / 2) * Math.PI); } }
在動畫中使用:
TanInterpolator tl = new TanInterpolator(); ObjectAnimator animator = ObjectAnimator.ofFloat(tv, "rotation", 0f, 360f); animator.setInterpolator(tl); animator.setDuration(5000); animator.start();
咦?這是什麼效果?這是一開始速度很大,然後逐漸減小到0的動畫效果.
原因如下:
看下圖,這是sin函式圖象:
x取0-0.5PI,y值則為0-1,這一段曲線的斜率逐漸減小至0,這也是為什麼我們的動畫一開始執行很快,後來速度逐漸變為0.
好了,看完這些,想必大家已經理解了這個類的使用了吧。
相關文章
- [譯]Android 動畫的靈魂—— InterpolatorAndroid動畫
- Android 動畫之Interpolator插入器Android動畫
- Android動畫的理解Android動畫
- Android動畫深入分析Android動畫
- 深入理解AndroidAndroid
- Android 之 TranslateAnimation類:位移動畫類Android動畫
- 深入理解CSS偽類CSS
- 深入理解CSS3 Animation 幀動畫CSSS3動畫
- 如何理解Android屬性動畫Android動畫
- 深入理解 Android 中的 MatrixAndroid
- 深入理解JavaScript中的類繼承JavaScript繼承
- 深入理解Java的介面和抽象類Java抽象
- 深入理解Android中的SharedPreferencesAndroid
- 深入理解Android中的ClassLoaderAndroid
- 深入理解python中的類和物件Python物件
- Java基礎——深入理解類的載入Java
- 深入理解ES6--9.JS的類JS
- Android 幀動畫使用Android動畫
- 深入理解JVM類載入器JVM
- 深入理解JVM類檔案格式JVM
- 深入理解JVM之類載入JVM
- Java類載入器深入理解Java
- 深入理解java巢狀類和內部類、匿名類Java巢狀
- Android 深入理解Android中的自定義屬性Android
- Android 深入理解 Notification 機制Android
- 深入理解JVM(四)類載入的時機JVM
- 深入理解java的抽象類和介面(轉載)Java抽象
- 一次Android動畫工具類的封裝Android動畫封裝
- [深入理解Android卷二 全文-第五章]深入理解PowerManagerServiceAndroid
- 再談屬性動畫——介紹以及自定義Interpolator插值器動畫
- 深入理解OSGi類載入機制
- 深入理解JVM類載入機制JVM
- Android全套動畫使用技巧Android動畫
- Android 中如何使用動畫Android動畫
- 深入理解 Android 中的各種 ContextAndroidContext
- 深入理解 Android 之 View 的繪製流程AndroidView
- [深入理解Android卷二 全文-第六章]深入理解ActivityManagerServiceAndroid
- [深入理解Android卷二 全文-第四章]深入理解PackageManagerServiceAndroidPackage