APIDemo动画之Interpolator

来源:互联网 发布:安哥拉伊斯兰教 知乎 编辑:程序博客网 时间:2024/06/05 19:42

      Interpolator 是被用来修饰动画效果,定义动画的变化率,可以使存在的动画效果accelerated(加速),decelerated(减速),repeated(重复),bounced(弹跳)等。
      Interpolator中文意思是插补器(百度翻译),而用在Android动画中,可以理解为是用于动画中的时间插值,其作用就是把0到1的浮点值变化映射到另一个浮点值变化。

插补器分为:

AccelerateDecelerateInterpolator 在动画开始与结束的地方速率改变比较慢,在中间的时候加速

AccelerateInterpolator 在动画开始的地方速率改变比较慢,然后开始加速

AnticipateInterpolator 开始的时候向后然后向前甩

AnticipateOvershootInterpolator 开始的时候向后然后向前甩一定值后返回最后的值

BounceInterpolator 动画结束的时候弹起

CycleInterpolator 动画循环播放特定的次数,速率改变沿着正弦曲线

DecelerateInterpolator 在动画开始的地方快然后慢

LinearInterpolator 以常量速率改变

OvershootInterpolator 向前甩一定值后再回到原来位置

       我们如果要实现一个动画效果,可以继承Animation,然后在applyTransformation(float interpolatedTime, Transformation t)这个方法内去实现具体效果,而这个方法的第一个参数interpolatedTime就是动画时间,Interpolator的作用就是改变这个时间。

     我们可以从源码看出,当一个动画调用了setInterpolator(Interpolator i),设置了插补器后,它是在什么时候启作用的呢?查看Animation.java这个动画父类,getTransformation(long currentTime, Transformation outTransformation),

public boolean getTransformation(long currentTime, Transformation outTransformation) {        if (mStartTime == -1) {            mStartTime = currentTime;        }        final long startOffset = getStartOffset();        final long duration = mDuration;        float normalizedTime;        if (duration != 0) {            normalizedTime = ((float) (currentTime - (mStartTime + startOffset))) /                    (float) duration;        } else {            // time is a step-change with a zero duration            normalizedTime = currentTime < mStartTime ? 0.0f : 1.0f;        }        final boolean expired = normalizedTime >= 1.0f;        mMore = !expired;        if (!mFillEnabled) normalizedTime = Math.max(Math.min(normalizedTime, 1.0f), 0.0f);        if ((normalizedTime >= 0.0f || mFillBefore) && (normalizedTime <= 1.0f || mFillAfter)) {            if (!mStarted) {                fireAnimationStart();                mStarted = true;                if (USE_CLOSEGUARD) {                    guard.open("cancel or detach or getTransformation");                }            }            if (mFillEnabled) normalizedTime = Math.max(Math.min(normalizedTime, 1.0f), 0.0f);            if (mCycleFlip) {                normalizedTime = 1.0f - normalizedTime;            }            final float interpolatedTime = mInterpolator.getInterpolation(normalizedTime);            applyTransformation(interpolatedTime, outTransformation);        }        if (expired) {            if (mRepeatCount == mRepeated) {                if (!mEnded) {                    mEnded = true;                    guard.close();                    fireAnimationEnd();                }            } else {                if (mRepeatCount > 0) {                    mRepeated++;                }                if (mRepeatMode == REVERSE) {                    mCycleFlip = !mCycleFlip;                }                mStartTime = -1;                mMore = true;                fireAnimationRepeat();            }        }        if (!mMore && mOneMoreTime) {            mOneMoreTime = false;            return true;        }        return mMore;    }

看37、38行那两句,mInterpolator变量就是我们前面调用setInterpolator设置的插补器对象,然后将mInterpolator.getInterpolation()的返回值当作第一个参数去执行applyTransformation,所以我们可以看出Interpolator对动画变化效果起到辅助作用的。我们就用平移动画效果来讲Interpolator是怎么起辅助作用的。

看下TranslateAnimation的applyTransformation方法

protected void applyTransformation(float interpolatedTime, Transformation t) {        float dx = mFromXDelta;        float dy = mFromYDelta;        if (mFromXDelta != mToXDelta) {            dx = mFromXDelta + ((mToXDelta - mFromXDelta) * interpolatedTime);        }        if (mFromYDelta != mToYDelta) {            dy = mFromYDelta + ((mToYDelta - mFromYDelta) * interpolatedTime);        }        t.getMatrix().setTranslate(dx, dy);    }

平移的(dx,dy)是根据参数interpolatedTime变化的,比如,我们给平移动画设置加速插补器AccelerateInterpolator

,这个插补器的变化是怎样的呢?


public float getInterpolation(float input) {        if (mFactor == 1.0f) {            return input * input;        } else {            return (float)Math.pow(input, mDoubleFactor);        }    }

默认的话即mFactor=1.0f,它是一个y=x^2(0<x<1)的变化曲线,如果你希望这个加速度更快点的话,可以使用这个构造函数

 public AccelerateInterpolator(float factor) {        mFactor = factor;        mDoubleFactor = 2 * mFactor;    }

这时它的变化曲线为y=x^(2*mFactor)(0<x<1),我们都知道这个函数是一个幂函数,是一个递增函数,变化速度越来越快,所以当平移动画设置了该加速插补器,它平移的速度是递增的。其他插补器这里就不多说了,请戳其他Interpolator说明

接下来我们看下效果

public class InterpolatorAnimationActivity extends Activity implementsAdapterView.OnItemSelectedListener {private static final String[] INTERPOLATORS = { "Accelerate", "Decelerate","Accelerate/Decelerate", "Anticipate", "Overshoot","Anticipate/Overshoot", "Bounce", "LinearInterpolator","CycleInterpolator" };@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_interpolator_animation);Spinner s = (Spinner) findViewById(R.id.spinner);ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,android.R.layout.simple_spinner_item, INTERPOLATORS);adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);s.setAdapter(adapter);s.setOnItemSelectedListener(this);}public void onItemSelected(AdapterView<?> parent, View v, int position,long id) {final View target = findViewById(R.id.target);final View targetParent = (View) target.getParent();Animation a = new TranslateAnimation(// 平移动画0.0f, targetParent.getWidth() - target.getWidth()- targetParent.getPaddingLeft()- targetParent.getPaddingRight(), 0.0f, 0.0f);a.setDuration(1000);a.setStartOffset(300);a.setRepeatMode(Animation.RESTART);a.setRepeatCount(Animation.INFINITE);switch (position) {case 0:// 加速插值器 速度变化公式y=x^2(默认)a.setInterpolator(AnimationUtils.loadInterpolator(this,android.R.anim.accelerate_interpolator));break;case 1:// 减速插值器a.setInterpolator(AnimationUtils.loadInterpolator(this,android.R.anim.decelerate_interpolator));break;case 2:// 加速减速插值器a.setInterpolator(AnimationUtils.loadInterpolator(this,android.R.anim.accelerate_decelerate_interpolator));break;case 3:a.setInterpolator(AnimationUtils.loadInterpolator(this,android.R.anim.anticipate_interpolator));break;case 4:a.setInterpolator(AnimationUtils.loadInterpolator(this,android.R.anim.overshoot_interpolator));break;case 5:a.setInterpolator(AnimationUtils.loadInterpolator(this,android.R.anim.anticipate_overshoot_interpolator));break;case 6:a.setInterpolator(AnimationUtils.loadInterpolator(this,android.R.anim.bounce_interpolator));break;case 7:a.setInterpolator(AnimationUtils.loadInterpolator(this,android.R.anim.linear_interpolator));break;case 8:a.setInterpolator(AnimationUtils.loadInterpolator(this,android.R.anim.cycle_interpolator));break;}target.startAnimation(a);}public void onNothingSelected(AdapterView<?> parent) {}}
activity_interpolator_animation.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:orientation="vertical"    android:padding="10dip"    android:layout_width="match_parent"    android:layout_height="wrap_content"    android:clipToPadding="false">    <TextView        android:id="@+id/target"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:textSize="26sp"        android:text="Interpolators"/>    <TextView        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:layout_marginTop="20dip"        android:layout_marginBottom="5dip"        android:text="Select an animation" />    <Spinner        android:id="@+id/spinner"        android:layout_width="match_parent"        android:layout_height="wrap_content" /></LinearLayout>


1 0
原创粉丝点击