我们知道属性动画控制动画执行的类有两个核心类,一个是插值器,一个是估值器
插值器决定改变趋势,也就是动画执行的快慢
估值器决定具体的数值,比如具体移动到哪个位置,旋转到什么角度
我们今天来说说插值器,Android系统内置了很多种差值器,基本可以满足平时的需求,但是有些时候我们需要一些特殊的动画,这时候就需要自定义插值器了
JAVA类 | 资源ID |
---|---|
AccelerateInterpolator | @android:anim/accelerate_interpolator |
OvershootInterpolator | @android:anim/overshoot_interpolator |
AccelerateDecelerateInterpolator | @android:anim/accelerate_decelerate_interpolator |
AnticipateInterpolator | @android:anim/anticipate_interpolator |
AnticipateOvershootInterpolator | @android:anim/anticipate_overshoot_interpolator |
BounceInterpolator | @android:anim/bounce_interpolator |
CycleInterpolator | @android:anim/cycle_interpolator |
DecelerateInterpolator | @android:anim/decelerate_interpolator |
LinearInterpolator | @android:anim/linear_interpolator |
系统默认的插值器是AccelerateDecelerateInterpolator
效果:
可能看起来比较乱,下面会逐个讲解一下,先说一下使用方法
xml中设置:
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="3000"
android:startOffset="1000"
android:fillBefore="true"
android:fillAfter="false"
android:fillEnabled="true"
android:repeatMode="restart"
android:repeatCount="infinite"
android:interpolator="@android:anim/overshoot_interpolator"
//上面这一行,设置插值器
android:fromXDelta="0"
android:toXDelta="200%"
android:fromYDelta="0"
android:toYDelta="0"
/>
//在代码中加载动画
Animation animation= AnimationUtils.loadAnimation(Activity2.this, R.anim.translate);
v.startAnimation(animation);
java中设置:
TranslateAnimation translateAnimation=new TranslateAnimation(
Animation.RELATIVE_TO_SELF,0f,Animation.RELATIVE_TO_SELF,2f,
Animation.RELATIVE_TO_SELF,0f,Animation.RELATIVE_TO_SELF,0f);
translateAnimation.setDuration(3000);
translateAnimation.setRepeatCount(Animation.INFINITE);
AccelerateInterpolator accelerateInterpolator=new AccelerateInterpolator();
translateAnimation.setInterpolator(accelerateInterpolator);
v.startAnimation(translateAnimation);
每一种插值器使用方法一致,只有CycleInterpolator需要穿一个float值,循环执行次数,会按正弦曲线来执行动画
AccelerateInterpolator
public AccelerateInterpolator() {
mFactor = 1.0f;
mDoubleFactor = 2.0;
}
public AccelerateInterpolator(float factor) {
mFactor = factor;
mDoubleFactor = 2 * mFactor;
}
public float getInterpolation(float input) {
if (mFactor == 1.0f) {
return input * input;
} else {
return (float)Math.pow(input, mDoubleFactor);
}
}
有两种构造方法,动画效果是加速,无参构造方法默认按平方上涨,传参数的话会按传的参数次平方上涨
OvershootInterpolator
public OvershootInterpolator() {
mTension = 2.0f;
}
public OvershootInterpolator(float tension) {
mTension = tension;
}
public float getInterpolation(float t) {
t -= 1.0f;
return t * t * ((mTension + 1) * t + mTension) + 1.0f;
}
有两个构造方法,动画效果是超过终点一定距离然后回弹,无参构造方法默认超出0.2,可以传float指定超出距离
AccelerateDecelerateInterpolator
public AccelerateDecelerateInterpolator() {
}
public float getInterpolation(float input) {
return (float)(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f;
}
只有一种空构造方法,效果是先加速后减速,无法改变参数
AnticipateInterpolator
public AnticipateInterpolator() {
mTension = 2.0f;
}
public AnticipateInterpolator(float tension) {
mTension = tension;
}
public float getInterpolation(float t) {
return t * t * ((mTension + 1) * t - mTension);
}
有两种构造方法,效果为后退一段距离再加速到终点,可传float指定后退的距离
AnticipateOvershootInterpolator
public AnticipateOvershootInterpolator() {
mTension = 2.0f * 1.5f;
}
public AnticipateOvershootInterpolator(float tension) {
mTension = tension * 1.5f;
}
public AnticipateOvershootInterpolator(float tension, float extraTension) {
mTension = tension * extraTension;
}
public float getInterpolation(float t) {
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);
}
有两种构造方法,动画效果为后退一段距离然后加速再超过终点位置再回弹回来,无参构造方法默认后退距离和超过终点的距离是0.2,可以传float指定距离,两个参数的构造方法不常用,可通过此方法指定距离,和一个参数的构造方法效果相同
BounceInterpolator
public BounceInterpolator() {
}
public float getInterpolation(float t) {
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;
}
只有一种空参构造方法,效果为加速到终点然后回弹几次,无法更改参数
CycleInterpolator
public CycleInterpolator(float cycles) {
mCycles = cycles;
}
public float getInterpolation(float input) {
return (float)(Math.sin(2 * mCycles * Math.PI * input));
}
只有一种float参数的构造方法,指定循环次数,效果是按照正弦函数不断跑
DecelerateInterpolator
public DecelerateInterpolator() {
}
public DecelerateInterpolator(float factor) {
mFactor = factor;
}
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;
}
有两种构造方法,效果是不断减速,空参构造方法默认系数为1.0,可通过构造方法设置,系数越高前期速度越快,减速效果越明显,设置为0.5时和线性插值器相同,小于0.5效果是加速
LinearInterpolator
public LinearInterpolator() {
}
public float getInterpolation(float input) {
return input;
}
线性插值器最为简单,效果是匀速前进,无法更改参数
自定义插值器
说完了系统内置的插值器,大致也明白了它的原理,让我们动手自己撸一个插值器吧
我们看源码可以发现插值器都实现了BaseInterpolator接口,但是这个接口版本太低了,随着属性动画的出现也出现了新的接口TimeInterpolator,我们需要实现getInterpolation()方法
private class CustomInterpolator implements TimeInterpolator, Interpolator {
@Override
public float getInterpolation(float input) {
float t2=input*input;
float t3=t2*input;
float result=(t3-2*t2+input)*5 + (-2*t3+3*t2) + (t3-t2)*5;
return result;
}
}
效果是会在中间黄油一下,我比较懒,没有写构造器去改变参数,看下图