Android属性动画 Interpolator
轉載請標明出處:http://blog.csdn.net/zhaoyanjun6/article/details/118683683
本文出自【趙彥軍的博客】
文章目錄
- Interpolator
- TimeInterpolator
- Interpolator
- BaseInterpolator
- 動畫分類
- BounceInterpolator 反彈動畫
- CycleInterpolator 循環動畫
- OvershootInterpolator 向前甩,越過終點,再回到終點
- AnticipateInterpolator 開始向后甩,然后向前
- AnticipateOvershootInterpolator 開始向后甩,然后向前甩,過沖到目標值,最后又回到了終值
- AccelerateDecelerateInterpolator 先加速后減速插值器
- DecelerateInterpolator 減速插值器
- 自定義 Interpolator
Interpolator
通俗易懂的說,Interpolator負責控制動畫變化的速率,使得基本的動畫效果能夠以勻速、加速、減速、拋物線速率等各種速率變化。
動畫是開發者給定開始和結束的“關鍵幀”,其變化的“中間幀”是有系統計算決定然后播放出來。因此,動畫的每一幀都將在開始和結束之間的特定時間顯示。此時動畫時間被轉換為時間索引,則動畫時間軸上的每個點都可以轉換成0.0到1.0之間的一個浮點數。然后再將該值用于計算該對象的屬性變換。在變換的情況下,y軸上,0.0對應于起始位置,1.0對應于結束位置,0.5對應于起始和結束之間的中間,對于一些插值器其值還可以是0~1之外的數值。
TimeInterpolator
/*** 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); }Interpolator
/*** An interpolator defines the rate of change of an animation. This allows* the basic animation effects (alpha, scale, translate, rotate) to be * accelerated, decelerated, repeated, etc.*/ 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. }BaseInterpolator
/*** An abstract class which is extended by default interpolators.*/ abstract public class BaseInterpolator implements Interpolator {private @Config int mChangingConfiguration;/*** @hide*/public @Config int getChangingConfiguration() {return mChangingConfiguration;}/*** @hide*/void setChangingConfiguration(@Config int changingConfiguration) {mChangingConfiguration = changingConfiguration;} }動畫分類
| AccelerateDecelerateInterpolator | @android:anim/accelerate_decelerate_interpolator | 開始和結束速率較慢,中間加速 |
| AccelerateInterpolator | @android:anim/accelerate_interpolator | 其變化開始速率較慢,后面加速 |
| DecelerateInterpolator | @android:anim/decelerate_interpolator | 開始速率較快,后面減速 |
| LinearInterpolator | @android:anim/linear_interpolator | 速率恒定 |
| AnticipateInterpolator | @android:anim/anticipate_interpolator | 開始向后甩,然后向前 |
| AnticipateOvershootInterpolator | @android:anim/anticipate_overshoot_interpolator | 開始向后甩,然后向前甩,過沖到目標值,最后又回到了終值 |
| OvershootInterpolator | @android:anim/overshoot_interpolator | 開始向前甩,過沖到目標值,最后又回到了終值 |
| BounceInterpolator | @android:anim/bounce_interpolator | 結束時反彈 |
| CycleInterpolator | @android:anim/cycle_interpolator | 循環播放,其速率為正弦曲線 |
在Android5.0開始,在 android.support.v4.view.animation包下又重新添加這三種插值器
- FastOutLinearInInterpolator 先加速然后勻速,本質還是加速運動,和Accelerate Interpolator類似
- LinearOutSlowInInterpolator 先勻速再減速,和Decelerate Interpolator類似
- FastOutSlowInInterpolator 先加速,然后減速,和Accelerate Decelerate Interpolator類似
BounceInterpolator 反彈動畫
class MainActivity : AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)var button: Button = findViewById(R.id.bt)button.animate().translationY(500f) //y軸向下平移.setStartDelay(2000) //延時2000秒,才開始執行動畫.setInterpolator(BounceInterpolator()) //設置減速插值器.setDuration(1500) //動畫執行時長800毫} }CycleInterpolator 循環動畫
class MainActivity : AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)var button: Button = findViewById(R.id.bt)button.animate().translationY(500f) //y軸向下平移.setStartDelay(2000) //延時2000秒,才開始執行動畫.setInterpolator(CycleInterpolator(3f)) //循環動畫,執行3次.setDuration(1500) //動畫執行時長800毫} }OvershootInterpolator 向前甩,越過終點,再回到終點
- 構造函數: public OvershootInterpolator (float tension)
tension : 張力值,默認為2,T越大,結束時的偏移越大,而且速度越快
class MainActivity : AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)var button: Button = findViewById(R.id.bt)button.animate().translationY(500f) //y軸向下平移.setStartDelay(2000) //延時2000秒,才開始執行動畫.setInterpolator(OvershootInterpolator()) //.setDuration(1500) //動畫執行時長800毫} }AnticipateInterpolator 開始向后甩,然后向前
- public AnticipateInterpolator(float tension)
- XML屬性: android:tension
張力值, 默認為2,T越大,初始的偏移越大,而且速度越快
class MainActivity : AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)var button: Button = findViewById(R.id.bt)button.animate().translationY(500f) //y軸向下平移.setStartDelay(2000) //延時2000秒,才開始執行動畫.setInterpolator(AnticipateInterpolator()) //.setDuration(1500) //動畫執行時長800毫} }AnticipateOvershootInterpolator 開始向后甩,然后向前甩,過沖到目標值,最后又回到了終值
class MainActivity : AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)var button: Button = findViewById(R.id.bt)button.animate().translationY(500f) //y軸向下平移.setStartDelay(2000) //延時2000秒,才開始執行動畫.setInterpolator(AnticipateOvershootInterpolator()) //.setDuration(1500) //動畫執行時長800毫} }AccelerateDecelerateInterpolator 先加速后減速插值器
DecelerateInterpolator 減速插值器
- 構造函數: public DecelerateInterpolator(float factor)
- XML屬性: android:factor
加速度參數. f越大,起始速度越快,但是速度越來越慢
自定義 Interpolator
首先看一下TimeInterpolator的接口定義,代碼如下所示:
/*** 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); }OK,接口還是非常簡單的,只有一個getInterpolation()方法。大家有興趣可以通過注釋來對這個接口進行詳解的了解,這里我就簡單解釋一下,getInterpolation()方法中接收一個input參數,這個參數的值會隨著動畫的運行而不斷變化,不過它的變化是非常有規律的,就是根據設定的動畫時長勻速增加,變化范圍是0到1。也就是說當動畫一開始的時候input的值是0,到動畫結束的時候input的值是1,而中間的值則是隨著動畫運行的時長在0到1之間變化的。
說到這個input的值,我覺得有不少朋友可能會聯想到我們使用過的fraction值。那么這里的input和fraction有什么關系或者區別呢?
答案很簡單,input的值決定了fraction的值。input的值是由系統經過計算后傳入到getInterpolation()方法中的,然后我們可以自己實現getInterpolation()方法中的算法,根據input的值來計算出一個返回值,而這個返回值就是fraction了。
因此,最簡單的情況就是input值和fraction值是相同的,這種情況由于input值是勻速增加的,因而fraction的值也是勻速增加的,所以動畫的運動情況也是勻速的。系統中內置的LinearInterpolator就是一種勻速運動的Interpolator,那么我們來看一下它的源碼是怎么實現的:
/*** An interpolator where the rate of change is constant*/ @HasNativeInterpolator public class LinearInterpolator extends BaseInterpolator implements NativeInterpolatorFactory {public LinearInterpolator() {}public LinearInterpolator(Context context, AttributeSet attrs) {}public float getInterpolation(float input) {return input;}/** @hide */@Overridepublic long createNativeInterpolator() {return NativeInterpolatorFactoryHelper.createLinearInterpolator();} }這里我們只看getInterpolation()方法,這個方法沒有任何邏輯,就是把參數中傳遞的input值直接返回了,因此fraction的值就是等于input的值的,這就是勻速運動的Interpolator的實現方式。
當然這是最簡單的一種Interpolator的實現了,我們再來看一個稍微復雜一點的。既然現在大家都知道了系統在默認情況下使用的是AccelerateDecelerateInterpolator,那我們就來看一下它的源碼吧,如下所示:
/*** An interpolator where the rate of change starts and ends slowly but* accelerates through the middle.* */ @HasNativeInterpolator public class AccelerateDecelerateInterpolator implements Interpolator, 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 */@Overridepublic long createNativeInterpolator() {return NativeInterpolatorFactoryHelper.createAccelerateDecelerateInterpolator();} }代碼雖然沒有變長很多,但是getInterpolation()方法中的邏輯已經明顯變復雜了,不再是簡單地將參數中的input進行返回,而是進行了一個較為復雜的數學運算。
那這里我們來分析一下它的算法實現,可以看到,算法中主要使用了余弦函數,由于input的取值范圍是0到1,那么cos函數中的取值范圍就是π到2π。而cos(π)的結果是-1,cos(2π)的結果是1,那么這個值再除以2加上0.5之后,getInterpolation()方法最終返回的結果值還是在0到1之間。只不過經過了余弦運算之后,最終的結果不再是勻速增加的了,而是經歷了一個先加速后減速的過程。
我們可以將這個算法的執行情況通過曲線圖的方式繪制出來,結果如下圖所示:
可以看到,這是一個S型的曲線圖,當橫坐標從0變化到0.2的時候,縱坐標的變化幅度很小,但是之后就開始明顯加速,最后橫坐標從0.8變化到1的時候,縱坐標的變化幅度又變得很小。
OK,通過分析LinearInterpolator和AccelerateDecelerateInterpolator的源碼,我們已經對Interpolator的內部實現機制有了比較清楚的認識了,那么接下來我們就開始嘗試編寫一個自定義的Interpolator。
編寫自定義Interpolator最主要的難度都是在于數學計算方面的,由于我數學并不是很好,因此這里也就寫一個簡單點的Interpolator來給大家演示一下。既然屬性動畫默認的Interpolator是先加速后減速的一種方式,這里我們就對它進行一個簡單的修改,讓它變成先減速后加速的方式。新建DecelerateAccelerateInterpolator類,讓它實現TimeInterpolator接口,代碼如下所示:
public class DecelerateAccelerateInterpolator implements TimeInterpolator{@Overridepublic float getInterpolation(float input) {float result;if (input <= 0.5) {result = (float) (Math.sin(Math.PI * input)) / 2;} else {result = (float) (2 - Math.sin(Math.PI * input)) / 2;}return result;}}這段代碼是使用正弦函數來實現先減速后加速的功能的,因為正弦函數初始弧度的變化值非常大,剛好和余弦函數是相反的,而隨著弧度的增加,正弦函數的變化值也會逐漸變小,這樣也就實現了減速的效果。當弧度大于π/2之后,整個過程相反了過來,現在正弦函數的弧度變化值非常小,漸漸隨著弧度繼續增加,變化值越來越大,弧度到π時結束,這樣從0過度到π,也就實現了先減速后加速的效果。
同樣我們可以將這個算法的執行情況通過曲線圖的方式繪制出來,結果如下圖所示:
可以看到,這也是一個S型的曲線圖,只不過曲線的方向和剛才是相反的。從上圖中我們可以很清楚地看出來,一開始縱坐標的變化幅度很大,然后逐漸變小,橫坐標到0.5的時候縱坐標變化幅度趨近于零,之后隨著橫坐標繼續增加縱坐標的變化幅度又開始變大,的確是先減速后加速的效果。
看看效果:
總結
以上是生活随笔為你收集整理的Android属性动画 Interpolator的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Android属性动画 ViewProp
- 下一篇: Android属性动画 ValueAni