Android -- Interpolator
如果android定義的interpolators不符合你的效果也可以自訂interpolators Interpolator介面 package android.animation; /** * 時間插值器定義了一個動畫的變動率。 * 這讓動畫讓非線性移動軌跡,例如加速和減速。 */public interface TimeInterpolator { /** * 將動畫已經消耗的時間的分數映射到一個表示插值的分數。 * 然後將插值與動畫的變化值相乘來推匯出當前已經過去的動畫時間的動畫變化量。 * * @param input 一個0到1.0表示動畫當前點的值,0表示開頭。1表示結尾 * @return 插值。它的值可以大於1來超出目標值,也小於0來空破底線。 */ float getInterpolation(float input);} TimeInterpolator是在Android API11時加入的之前類就叫Interpolator。 package android.view.animation; import android.animation.TimeInterpolator; /** * * 一個定義動畫變動率的插值器。 * 它允許對基本的(如透明,縮放,平移,旋轉)進行加速,減速,重複等動畫效果 */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.} /** * 一個開始很慢然後不斷加速的插值器。 */public class AccelerateInterpolator implements Interpolator { private final float mFactor; private final double mDoubleFactor; public AccelerateInterpolator() { mFactor = 1.0f; mDoubleFactor = 2.0; } /** * * @param factor * 動畫的快慢度。將factor設定為1.0f會產生一條y=x^2的拋物線。增加factor到1.0f之後為加大這種漸入效果(也就是說它開頭更加慢,結尾更加快) */ public AccelerateInterpolator(float factor) { mFactor = factor; mDoubleFactor = 2 * mFactor; } public AccelerateInterpolator(Context context, AttributeSet attrs) { TypedArray a = context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.AccelerateInterpolator); mFactor = a.getFloat(com.android.internal.R.styleable.AccelerateInterpolator_factor, 1.0f); mDoubleFactor = 2 * mFactor; a.recycle(); } @Override public float getInterpolation(float input) { if (mFactor == 1.0f) { return input * input; } else { return (float)Math.pow(input, mDoubleFactor); } }} 加速的快慢度由參數fractor決定。當fractor值為1.0f時,動畫加速軌跡相當於一條y=x^2的拋物線。 image 當fractor不為1時,軌跡曲線是y=x^(2*fractor)(0<x<=1)的曲線。(當fractor為4時) image 如果你在使用AccelerateInterpolator時,想要那種一開始很慢,然後突然就很快的加速的動畫效果的話,就將fractor設定大點。 DecelerateInterpolator /** * 一個開始比較快然後減速的插值器 * */public class DecelerateInterpolator implements Interpolator { public DecelerateInterpolator() { } /** * * @param factor * 動畫的快慢度。將factor值設定為1.0f時將產生一條從上向下的y=x^2拋物線。 * 增加factor到1.0f以上將使漸入的效果增強(也就是說,開頭更快,結尾更慢) */ public DecelerateInterpolator(float factor) { mFactor = factor; } public DecelerateInterpolator(Context context, AttributeSet attrs) { TypedArray a = context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.DecelerateInterpolator); mFactor = a.getFloat(com.android.internal.R.styleable.DecelerateInterpolator_factor, 1.0f); a.recycle(); } @Override public float getInterpolation(float input) { float result; if (mFactor == 1.0f) { result = (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;} /** * 一個變動率開始慢從中間後開始變快。 */public class AccelerateDecelerateInterpolator implements Interpolator { public AccelerateDecelerateInterpolator() { } @SuppressWarnings({"UnusedDeclaration"}) public AccelerateDecelerateInterpolator(Context context, AttributeSet attrs) { } @Override public float getInterpolation(float input) { return (float)(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f; }} public class LinearInterpolator implements Interpolator { public LinearInterpolator() { } public LinearInterpolator(Context context, AttributeSet attrs) { } public float getInterpolation(float input) { return input; }} /** * 這個插值器的插值在後面呈彈跳狀態。 */public class BounceInterpolator implements Interpolator { public BounceInterpolator() { } @SuppressWarnings({"UnusedDeclaration"}) public BounceInterpolator(Context context, AttributeSet attrs) { } private static float bounce(float t) { return t * t * 8.0f; } @Override public float getInterpolation(float t) { // _b(t) = t * t * 8 // bs(t) = _b(t) for t < 0.3535 // bs(t) = _b(t - 0.54719) + 0.7 for t < 0.7408 // bs(t) = _b(t - 0.8526) + 0.9 for t < 0.9644 // bs(t) = _b(t - 1.0435) + 0.95 for t <= 1.0 // b(t) = bs(t * 1.1226) t *= 1.1226f; if (t < 0.3535f) return bounce(t); else if (t < 0.7408f) return bounce(t - 0.54719f) + 0.7f; else if (t < 0.9644f) return bounce(t - 0.8526f) + 0.9f; else return bounce(t - 1.0435f) + 0.95f; }} /** * 一個開始向後蕩,然後向前蕩的插值器。 */public class AnticipateInterpolator implements Interpolator { private final float mTension; public AnticipateInterpolator() { mTension = 2.0f; } /** * @param tension * 繃緊程度,當繃緊程式為0.0f時,也就沒有了反向作用力。插值器將退化成一個y=x^3的加速插值器。 */ public AnticipateInterpolator(float tension) { mTension = tension; } public AnticipateInterpolator(Context context, AttributeSet attrs) { TypedArray a = context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.AnticipateInterpolator); mTension = a.getFloat(com.android.internal.R.styleable.AnticipateInterpolator_tension, 2.0f); a.recycle(); } @Override public float getInterpolation(float t) { // a(t) = t * t * ((tension + 1) * t - tension) return t * t * (((mTension + 1) * t) - mTension); }} /** * 一個插值器它開始向上推,然後向下蕩,蕩過最低線。然後再回到最低線。 * <hr/> * An interpolator where the change starts backward then flings forward and overshoots * the target value and finally goes back to the final value. */public class AnticipateOvershootInterpolator implements Interpolator { private final float mTension; public AnticipateOvershootInterpolator() { mTension = 2.0f * 1.5f; } /** * @param tension * anticipation/overshoot的比值。當和tension值為0.0f時, * 也就沒有anticipation/overshoot的比值了,插值器退化為一個加速/減速插值器。 */ public AnticipateOvershootInterpolator(float tension) { mTension = tension * 1.5f; } /** * @param tension Amount of anticipation/overshoot. When tension equals 0.0f, * there is no anticipation/overshoot and the interpolator becomes * a simple acceleration/deceleration interpolator. * @param extraTension * 乘以tension的值。例如,在上面建構函式中extraTension的值為1.5f */ public AnticipateOvershootInterpolator(float tension, float extraTension) { mTension = tension * extraTension; } public AnticipateOvershootInterpolator(Context context, AttributeSet attrs) { TypedArray a = context.obtainStyledAttributes(attrs, AnticipateOvershootInterpolator); mTension = a.getFloat(AnticipateOvershootInterpolator_tension, 2.0f) * a.getFloat(AnticipateOvershootInterpolator_extraTension, 1.5f); a.recycle(); } private static float a(float t, float s) { return t * t * (((s + 1) * t) - s); } private static float o(float t, float s) { return t * t * (((s + 1) * t) + s); } @Override public float getInterpolation(float t) { // a(t, s) = t * t * ((s + 1) * t - s) // o(t, s) = t * t * ((s + 1) * t + s) // f(t) = 0.5 * a(t * 2, tension * extraTension), when t < 0.5 // f(t) = 0.5 * (o(t * 2 - 2, tension * extraTension) + 2), when t <= 1.0 if (t < 0.5f) return 0.5f * a(t * 2.0f, mTension); else return 0.5f * (o((t * 2.0f) - 2.0f, mTension) + 2.0f); }} /** * 以指定的周期重複動畫。變動率曲線為正弦。 */public class CycleInterpolator implements Interpolator { /** * * @param cycles 要重複的周期數 */ public CycleInterpolator(float cycles) { mCycles = cycles; } public CycleInterpolator(Context context, AttributeSet attrs) { TypedArray a = context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.CycleInterpolator); mCycles = a.getFloat(com.android.internal.R.styleable.CycleInterpolator_cycles, 1.0f); a.recycle(); } @Override public float getInterpolation(float input) { return (float)(Math.sin(2 * mCycles * Math.PI * input)); } private float mCycles;} /** * An interpolator where the change flings forward and overshoots the last value * then comes back. */public class OvershootInterpolator implements Interpolator { private final float mTension; public OvershootInterpolator() { mTension = 2.0f; } /** * @param tension Amount of overshoot. When tension equals 0.0f, there is * no overshoot and the interpolator becomes a simple * deceleration interpolator. */ public OvershootInterpolator(float tension) { mTension = tension; } public OvershootInterpolator(Context context, AttributeSet attrs) { TypedArray a = context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.OvershootInterpolator); mTension = a.getFloat(com.android.internal.R.styleable.OvershootInterpolator_tension, 2.0f); a.recycle(); } @Override public float getInterpolation(float t) { // _o(t) = t * t * ((tension + 1) * t + tension) // o(t) = _o(t - 1) + 1 t -= 1.0f; return (t * t * (((mTension + 1) * t) + mTension)) + 1.0f; //plot {(x-1)(x-1)((tension+1)(x-1)+tension)+1,(0<x<=1)} }}