APIDemo动画之Interpolator

      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 implements
		AdapterView.OnItemSelectedListener {
	private static final String[] INTERPOLATORS = { "Accelerate", "Decelerate",
			"Accelerate/Decelerate", "Anticipate", "Overshoot",
			"Anticipate/Overshoot", "Bounce", "LinearInterpolator",
			"CycleInterpolator" };

	@Override
	public 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>

APIDemo动画之Interpolator_第1张图片

你可能感兴趣的:(android,android,interpolator)