滲透理解Animation時間插值Interpolator類,interpolator
========================================================
作者:qiujuer
部落格:blog.csdn.net/qiujuer
網站:www.qiujuer.net
開源庫:Genius-Android
轉載請註明出處:http://blog.csdn.net/qiujuer/article/details/42430269
========================================================
序
- 一個好的動畫一定是用心做出來的,何為用心?其中一點我認為定義適當的 Interpolator 就是一種用心的表現;這點在 google material design 中尤為明顯。
- 一個好的動畫一定要符合實際,一句老的話就是:石頭下落一定要受重力才優雅,不然一顆石頭像羽毛一樣在風中還飄啊飄的那就不行了。
介紹Interpolator 是個什麼東西?
說到 Interpolator 啊,這個要從3年前說起,話說當年Google、諾基亞、Qiujuer 三分天下.... 哈哈,開個玩笑~
Interpolator 這個時間插值類,其主要使用在動畫中,其作用主要是控制目標變數的變化值進行對應的變化。
你可以這麼理解,現在小明去買醬油,規定時間是1個小時到達,裡程是1公裡;現在小明心裡唯恐無法達到,所以先跑起來了,但因為體力消耗所以逐漸的慢下來了;然後成功到達。這樣的一個過程中把小明逐漸慢下來的這個過程抽象出來也就是 Interpolator 的工作;當然 Interpolator 也可以控制小明先慢慢熱身然後越跑越快最後達到。
這些都是 Interpolator 能完成的工作,同樣 Interpolator 還能控制一個彈球掉在地上彈起來逐漸降低的過程,這些都是可以控制的。
Interpolator 的原理?
public interface Interpolator extends 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);}其操作在所繼承的介面中,在所繼承的介面中有一個方法 float getInterpolation(float input);
在這個方法中,傳入的值是一個0.0~1.0的值,返回值可以小於0.0也可以大於1.0。
你可以這麼理解:在Animation中時間是正常的走的,你設定了200ms,現在走到了100ms了,那麼按照線性來說現在應該是走了一半的路程也就是0.5;現在就把這0.5傳遞給Interpolator 讓 Interpolator 告訴我走到一半時間的時候此時小明在哪裡;這也就是 Interpolator 的原理。
常用類
哎呀我的天天啊,訪問不了Google就是麻煩,只能從源碼了:
Android 官方提供的就是這麼十種,是9種還是10種啊,沒有數錯吧。分別是:
源碼
這裡說幾個簡單的源碼
LinearInterpolator
@HasNativeInterpolatorpublic class LinearInterpolator implements Interpolator, NativeInterpolatorFactory { public LinearInterpolator() { } public LinearInterpolator(Context context, AttributeSet attrs) { } public float getInterpolation(float input) { return input; } /** @hide */ @Override public long createNativeInterpolator() { return NativeInterpolatorFactoryHelper.createLinearInterpolator(); }}最簡單的一個由於是線性,所以直接返回。
DecelerateInterpolator
public class DecelerateInterpolator implements Interpolator, NativeInterpolatorFactory { public DecelerateInterpolator() { } /** * Constructor * * @param factor Degree to which the animation should be eased. Setting factor to 1.0f produces * an upside-down y=x^2 parabola. Increasing factor above 1.0f makes exaggerates the * ease-out effect (i.e., it starts even faster and ends evens slower) */ public DecelerateInterpolator(float factor) { mFactor = factor; } public DecelerateInterpolator(Context context, AttributeSet attrs) { this(context.getResources(), context.getTheme(), attrs); } /** @hide */ public DecelerateInterpolator(Resources res, Theme theme, AttributeSet attrs) { TypedArray a; if (theme != null) { a = theme.obtainStyledAttributes(attrs, R.styleable.DecelerateInterpolator, 0, 0); } else { a = res.obtainAttributes(attrs, R.styleable.DecelerateInterpolator); } mFactor = a.getFloat(R.styleable.DecelerateInterpolator_factor, 1.0f); a.recycle(); } public float getInterpolation(float input) { float result; if (mFactor == 1.0f) { result = (float)(1.0f - (1.0f - input) * (1.0f - input)); } else { result = (float)(1.0f - Math.pow((1.0f - input), 2 * mFactor)); } return result; } private float mFactor = 1.0f; /** @hide */ @Override public long createNativeInterpolator() { return NativeInterpolatorFactoryHelper.createDecelerateInterpolator(mFactor); }}從其中可以看出,其並不是一個簡單的類,其是是可以通過 XML 進行設定的類,通過 XML 可以設定其中的 mFactor 變數,其值預設是1.0;值越大其變化越快;得到的結果就是,開始的時候更加的快,其結果就是更加的慢,好比一個人開始跑的很快,但是換來的就是後面的路程將會花更多時間慢慢走。
在方法
public float getInterpolation(float input) { float result; if (mFactor == 1.0f) { result = (float)(1.0f - (1.0f - input) * (1.0f - input)); } else { result = (float)(1.0f - Math.pow((1.0f - input), 2 * mFactor)); } return result; }其描述的是一個初中學的拋物方程(話說是初中吧),y = x^2 我擦不知道怎麼弄上去,就這樣吧;意思懂就OK。
由於篇幅就說這麼兩個;下面說說其他東西。
動畫表
這個圖片相信前段時間看的不少吧?前段時間 material design 剛剛出來的時候好多人說這個啊,但是好像都是說圖,但是沒有說說其如何?吧。
實現
這裡送上福利,其是最開始我發現的是 C++ 的版本:
float Elastic::easeIn (float t,float b , float c, float d) { if (t==0) return b; if ((t/=d)==1) return b+c; float p=d*.3f; float a=c; float s=p/4; float postFix =a*pow(2,10*(t-=1)); // this is a fix, again, with post-increment operators return -(postFix * sin((t*d-s)*(2*PI)/p )) + b;} float Elastic::easeOut(float t,float b , float c, float d) { if (t==0) return b; if ((t/=d)==1) return b+c; float p=d*.3f; float a=c; float s=p/4; return (a*pow(2,-10*t) * sin( (t*d-s)*(2*PI)/p ) + c + b); } float Elastic::easeInOut(float t,float b , float c, float d) { if (t==0) return b; if ((t/=d/2)==2) return b+c; float p=d*(.3f*1.5f); float a=c; float s=p/4; if (t < 1) { float postFix =a*pow(2,10*(t-=1)); // postIncrement is evil return -.5f*(postFix* sin( (t*d-s)*(2*PI)/p )) + b; } float postFix = a*pow(2,-10*(t-=1)); // postIncrement is evil return postFix * sin( (t*d-s)*(2*PI)/p )*.5f + c + b;}
參數的意思:
- t – 動畫中當前的時間
- b – 開始值
- c – 結束值
- d – 動畫的總時間
看看 Java 的 第一行前三個的:
public class Sine {public static float easeIn(float t,float b , float c, float d) {return -c * (float)Math.cos(t/d * (Math.PI/2)) + c + b;}public static float easeOut(float t,float b , float c, float d) {return c * (float)Math.sin(t/d * (Math.PI/2)) + b;}public static float easeInOut(float t,float b , float c, float d) {return -c/2 * ((float)Math.cos(Math.PI*t/d) - 1) + b;}}雖然 Java 的也有了,但是話說這個怎麼用啊,跟上面的Interpolator如何聯絡起來啊?
一個簡單的方法:首先把 d 總時間設定為固定值 1.0 ,把 b 開始值設定為 0.0 把結束值設定為1.0,然後把 t 當作上面 Interpolator 中的 float getInterpolation(float input);傳入值,此時不就能用上了?對不?
舉個Case
/** * Created by Qiujuer on 2015/1/5. */public class InSineInterpolator implements Interpolator{ public static float easeIn(float t,float b , float c, float d) { return -c * (float)Math.cos(t/d * (Math.PI/2)) + c + b; } @Override public float getInterpolation(float input) { return easeIn(input, 0, 1, 1); }}使用
//AnimatorSet mAnimatorSet = new AnimatorSet(); mAnimatorSet.playTogether(aPaintX, aPaintY, aRadius, aBackground); mAnimatorSet.setInterpolator(new InSineInterpolator()); mAnimatorSet.start();
可以看出使用與上面 Android 內建的完全一樣,當然這個只是一個 Case ,具體使用中你可以隨意封裝,前提是別改動了主要部分。
好了,完成了,擦又是三個小時過去了,我的 LOL 又沒法打了。
最後送上福利,全部的實作類別:
Animation Interpolator.zip
願大家都能做出自己滿意的動畫!
——學之開源,用於開源;初學者的心態,與君共勉!
========================================================
作者:qiujuer
部落格:blog.csdn.net/qiujuer
網站:www.qiujuer.net
開源庫:Genius-Android
轉載請註明出處:http://blog.csdn.net/qiujuer/article/details/42430269
========================================================