1、自定义视图动画,这个比较简单,直接上代码:
public class MyAnimation extends Animation { private int mCenterWidth,mCenterHeight; public MyAnimation(int mCenterWidth,int mCenterHeight){ this.mCenterWidth = mCenterWidth; this.mCenterHeight = mCenterHeight; } //自定義視圖動畫的主要邏輯 @Override protected void applyTransformation(float interpolatedTime, Transformation t) { Log.e("time",interpolatedTime+""); final Matrix matrix = t.getMatrix(); matrix.preScale(1,1-interpolatedTime,mCenterWidth,mCenterHeight); } }
2、自定义插值器,这个也直接上代码:
public class MyInterpolator implements android.view.animation.Interpolator { //自定義插值器的主要邏輯 @Override public float getInterpolation(float input) { return input*2; } }
3、主要讲解他们之间是如何工作的:
这是Animation基类中的getTranslation方法:
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 float interpolatedTime = mInterpolator.getInterpolation(normalizedTime); applyTransformation(interpolatedTime, outTransformation); }从一二节我们发现:自定义视图动画的主要逻辑是重写applyTranformation方法而自定义插值器的主要逻辑是重写getInterpolation
方法,然而从上面的final float interpolatedTime = mInterpolator.getInterpolation(normalizedTime);applyTransformation(interpolatedTime, outTransformation);这两行代码可以得知插值器的getInterpolator的返回值作为applyTransformation的第一个参数。他们的引用关系是知道了?但是这两个方法的参数是如何得到的呢,有什么作用呢?1)由上面的代码块可知getInterpolation的参数normalizedTime是其实就是已完成的时间跟总时长的比,所以取值范围是0~1,我们可以通过某个函数并根据normalizedTime的值去运算得到一个有特定规律的值序列,就像是一些三角函数之类的。2)而在applyTransformation方法中接收到对应的由getInterpolator计算出来的值后,结合第一个参数就可以实现一些特定的效果了。
4、举例:DecelerateInterpolator: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;我们假如直接使用默认构造方法则mFactor=1.0f,由此可知返回值是由小到大的,并且变化速率越来越小;TranslationAnimation:
@Override 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 = mFromXDelta + ((mToXDelta - mFromXDelta) * interpolatedTime);可以发现dx是与interpolatedTime成正比的;再加上DecelerateInterpolator的getInterpolation返回值的增长速度是从块变慢的,所以就实现了TranslationAnimation动画的是平移量是增加的,只是增加的速度变慢的。
示例分析总结:根据对DecelerateInterpolator和TranslationAnimation的源代码解析自定义插值器的返回值一般都是增长的只是增长的速率可以是由慢变快(AccelerateInterpolator)和由快变慢(DecelerateInterpolator等,而自定义动画的效果变化量一般与interpolatedTime参数成正比:
warn:一开始我在认识插值器的时候发现他的核心方法是getInterpolator的时候,结合他的参数input和TranslationAnimation等系统
实现的animation类,以为getInterpolator的参数就是TransitionAnimation的fromXDelta和toXDelta之间的某个值,这是非常错误的。