概述
Interpolator属性是一个Animation类的一个XML属性,所以alpha,scale,rotate,translate,set都会继承得到这个属性.Interpolator被译为插值器,其实就是一个管理动画播放变化的一个属性.系统自带了一些插值器会让动画在播放过程中有更多的展示形式.
Interpolator的系统值
- AccelerateDecelerateInterpolator 在动画开始与介绍的地方速率改变比较慢,在中间的时候加速
- AccelerateInterpolator 在动画开始的地方速率改变比较慢,然后开始加速
- AnticipateInterpolator 开始的时候向后然后向前甩
- AnticipateOvershootInterpolator 开始的时候向后然后向前甩一定值后返回最后的值
- BounceInterpolator 动画结束的时候弹起
- CycleInterpolator 动画循环播放特定的次数,速率改变沿着正弦曲线
- DecelerateInterpolator 在动画开始的地方快然后慢
- LinearInterpolator 以常量速率改变
-
OvershootInterpolator 向前甩一定值后再回到原来位置
效果图示:
Interpolator的代码使用
ScaleAnimation interpolateScaleAnim=new ScaleAnimation(0.0f,1.4f,0.0f,1.4f,Animation.RELATIVE_TO_SELF,0.5f,Animation.RELATIVE_TO_SELF,0.5f);
interpolateScaleAnim.setInterpolator(new BounceInterpolator());
interpolateScaleAnim.setDuration(3000);
Interpolator的XML文件使用
<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:fromXScale="0.0"
android:toXScale="1.4"
android:fromYScale="0.0"
android:toYScale="1.4"
android:pivotX="50%"
android:pivotY="50%"
android:duration="700"
android:fillAfter="true"
/>
自定义插值器
- 自定义插值器一般用于属性动画,所以我们首先看看,属性动画的简单使用代码段:
ValueAnimator animator = ValueAnimator.ofInt(0,600);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
int curValue = (int)animation.getAnimatedValue();
tv.layout(tv.getLeft(),curValue,tv.getRight(),curValue+tv.getHeight());
}
});
animator.setDuration(1000);
animator.setEvaluator(new IntEvaluator());
animator.setInterpolator(new BounceInterpolator());
animator.start();
我们可以看出,ValueAnimator的原理是通过监听数值变化进度,来实时改变View的属性从而达到动画的效果,而onAnimationUpdate所得到的动画进度,就来自Interpolator(插值器)
- 让我们先看看系统的插值器是怎么定义的:
public class LinearInterpolator implements Interpolator {
public LinearInterpolator() {
}
public LinearInterpolator(Context context, AttributeSet attrs) {
}
public float getInterpolation(float input) {
return input;
}
}
public interface Interpolator extends TimeInterpolator {
}
LinearINterpolator实现了Interpolator接口则直接继承自TimeInterpolator,而且并没有添加任何其他的方法.
让我们再看看TimeInterpolator接口做了什么?
public interface TimeInterpolator {
float getInterpolation(float input);
}
我们可以看到,它里面只有一个函数float getInterpolation(float input);
我们来看看这个方法是干嘛的.
参数input:参数是一个float类型的值,它的取值范围是0-1,表示动画的进度,取0时表示动画刚开始,即1表示动画刚结束,
返回值:表示当前要显示的参数,取值也可以超过1也可以小于0,超过1代表超过目标值,小于0表示小于开始位置.
Evaluator
概述
不是要讲插值器,这个Evaluator是什么东西?别急我们先看看下面的图:
这幅图讲述了从定义动画的数字区间到通过AnimationUpdateListener中得到当前动画所对应的数值的整个过程.下面我们对这4个步骤具体讲解一下:
- ofInt(0,400)表示指定动画的数字区间,是从0-400运动.
- 加速器:上面我们说了,动画开始后,通过加速器会返回当前的动画进度所对应的数字进度,但这个数字进度是百分制的,以小数表示,如0.2
- Evaluator:我们知道我们通过监听器拿到的是当前动画所对应的数值,而不是百分制的进度.那么就必须有一个地方会根据当前的数字进度,将其转换为对应的数值,这个地方就是Evaluator;Evaluator就是将加速器返回的数字进度转成对应数字的数字值.也就是下面公式:
当前的值 = 100 + (400 - 100)* 显示进度
- 监听器:我们通过在AnimatorUpdateListener监听器使用
animation.getAnimatedValue()
函数拿到Evaluator中返回的值.
所以说Evaluator就是一个计算器.
各种Evaluator
首先,加速器返回的都是小数值,表示的是当前动画的数值进度.无论是利用ofFloat()还是利用ofInt()定义的动画都是适用的.因为无论什么动画,它的进度必然都在0到1之间,0表示没开始,1表示已经结束,对于任何动画都是适用的.
但是Evaluator不一样,我们知道Evaluator是根据加速器返回的小数进度转换成当前数值进度所对应的值,那么问题就来了,如果我们使用ofInt来定义动画,得到的必然是int型,如果使用ofFloat来定义动画,得到的必然是Float型.每种定义方式使用的Evaluator必然是不同的,所以我们使用animator.setEvaluator()来设置Evaluator.具体代码如下:
<embed id="ZeroClipboardMovie_9" src="https://csdnimg.cn/public/highlighter/ZeroClipboard.swf" loop="false" menu="false" quality="best" bgcolor="#ffffff" width="16" height="16" name="ZeroClipboardMovie_9" align="middle" allowscriptaccess="always" allowfullscreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="id=9&width=16&height=16" wmode="transparent" style="box-sizing: border-box;">
1. ValueAnimator animator = ValueAnimator.ofInt(0,600);
3. animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
4. @Override
5. public void onAnimationUpdate(ValueAnimator animation) {
6. int curValue = (int)animation.getAnimatedValue();
7. tv.layout(tv.getLeft(),curValue,tv.getRight(),curValue+tv.getHeight());
8. }
9. });
10. animator.setDuration(1000);
11. animator.setEvaluator(new IntEvaluator());
12. animator.setInterpolator(new BounceInterpolator());
13. animator.start();
这时候就有人问了,之前我们直接使用ofInt()或者ofFloat定义动画也不会有问题啊?因为onInt和onFloat都是系统直接提供的函数,所以在使用时都会有默认的加速器和Evaluator来使用,不指定则使用默认的;对于Evaluator而言,ofInt()的默认Evaluator是IntEvaluator,ofFloat()的默认Evaluator是FloatEvaluator.
我们已经弄清楚Evaluator是干什么的了,接下来我们就以IntEvaluator看看内部都做了什么?
public class IntEvaluator implements TypeEvaluator<Integer> {
public Integer evaluate(float fraction, Integer startValue, Integer endValue) {
int startInt = startValue;
return (int)(startInt + fraction * (endValue - startInt));
}
}
我们可以看到在IntEvaluator中只有一条函数(int)(startInt + fraction * (endValue - startInt));
其中fraction就是加速器返回值,startInt代表动画起始值,endValue代表动画结束值.这两个值由ofInt传入.这个公式整个所做的工作就是上面提到的
当前的值 = 100 + (400 - 100)* 显示进度
自定义Evalutor
上面我们看了IntEvaluator的代码,我们仿照IntEvaluator的实现方法,我们自定义一个MyEvalutor,首先实现了TypeEvaluator接口:
public class MyEvaluator implements TypeEvaluator<Integer> {
@Override
public Integer evaluate(float fraction, Integer startValue, Integer endValue) {
return (int)(200+startInt + fraction * (endValue - startInt));
}
}
我们看到这里使用了泛型,利用泛型我们可以自定义函数evaluate(float fraction, Integer startValue, Integer endValue)
返回的类型,而在该方法内加入我们所需要的计算逻辑,从而制定我们需要的计算器.
如果我们需要输出一个倒序播放动画效果,只需要在evaluate方法中写入
return (int) (endValue - fraction * (endValue - startInt));
ArgbEvalutor
上面我们讲了IntEvaluator和FloatEvalutor,其实在android.animation包下,还有一个Evaluator叫ArgbEvalutor.
ArgbEvalutor是用来做颜色过渡转换的,可能是开发人员贴心的害我我们不太懂颜色怎么变换.来看代码:
public class ArgbEvaluator implements TypeEvaluator {
public Object evaluate(float fraction, Object startValue, Object endValue) {
int startInt = (Integer) startValue;
int startA = (startInt >> 24);
int startR = (startInt >> 16) & 0xff;
int startG = (startInt >> 8) & 0xff;
int startB = startInt & 0xff;
int endInt = (Integer) endValue;
int endA = (endInt >> 24);
int endR = (endInt >> 16) & 0xff;
int endG = (endInt >> 8) & 0xff;
int endB = endInt & 0xff;
return (int)((startA + (int)(fraction * (endA - startA))) << 24) |
(int)((startR + (int)(fraction * (endR - startR))) << 16) |
(int)((startG + (int)(fraction * (endG - startG))) << 8) |
(int)((startB + (int)(fraction * (endB - startB))));
}
}
我们这里关注两个地方,第一:返回类型是int类型,这说明我们可以用ofInt来初始化数值范围,第二:颜色值包括A,R,G,B四个值,每个值是8位所以用16进制表示一个颜色应该是0xffff0000(纯红色)
下面我们就使用一下ArgbEvaluator.
ValueAnimator animator = ValueAnimator.ofInt(0xffffff00,0xff0000ff);
animator.setEvaluator(new ArgbEvaluator());
animator.setDuration(3000);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
int curValue = (int)animation.getAnimatedValue();
tv.setBackgroundColor(curValue);
}
});
animator.start();
文章来自
http://blog.csdn.net/harvic880925/article/details/50546884