1 插值器(Interpolator)简介
插值器(Interpolator)是设置动画运行过程中的变化规律,类似匀速变化,加速变化,回弹等。
补间动画Animation设置插值器的两个函数:
public void setInterpolator(Context context, @AnimRes @InterpolatorRes int resID) ;
public void setInterpolator(Interpolator i) ;
xml动画配置文件中设置插值器代码:
android:interpolator="@android:anim/linear_interpolator"
上面的setInterpolator函数和 android:interpolator属性就是设置动画的插值器。
实际使用动画过程中,有时可能不完全都是要求动画匀速运动,类似加速运动,仿抛物线运动等,都需要插值器的配合。
2系统提供的默认插值器
可以看到除了BaseInterpolator(抽象类,不讨论)外有10种系统提供的插值器。下面从xml中引用插值器的字段和插值器对应的具体类和插值器的作用三方面来介绍系统提供的插值器。
@android:anim/linear_interpolator 对应 LinearInterpolator
作用:动画匀速改变@android:anim/decelerate_interpolator 对应 DecelerateInterpolator
作用:动画运行越来越慢,减速运行 ,说明开始的时候是最高速。@android:anim/accelerate_interpolator 对应 AccelerateInterpolator
作用:动画加速进行,动画开始运行时变化很慢,越到后面越快,最后突然结束。@android:anim/accelerate_decelerate_interpolator 对应java类AccelerateDecelerateInterpolator
作用 :动画先加速再减速,相当于view速度从0一直加速,最后又减速到0,默认插值器。@android:anim/anticipate_interpolator 对应 AnticipateInterpolator
作用:先退后再加速前进 ,类似投掷标枪,先往后一点,然后加速运行。@android:anim/anticipate_overshoot_interpolator 对应java类AnticipateOvershootInterpolator
作用:先退后再加速前进,超出终点后再回终点@android:anim/bounce_interpolator 对应 BounceInterpolator
作用:最后阶段弹球效果,就是会在到达终点后,类似弹球回弹几次。@android:anim/cycle_interpolator 对应CycleInterpolator
作用:周期运动,动画可以不到终点就回弹,也可以到了终点后在回弹,还可以回弹多次,小于1.0f不到终点就回弹,大于1.0f会到了终点后回弹,如果大于2,则会回弹多次。下面的例子会设置5次,大家可以看效果。@android:anim/overshoot_interpolator 对应 OvershootInterpolator
作用:快速完成动画,会超出一点然后再回到结束样式。@android:anim/path_interpolator 对应 PathInterpolator,
作用:根据路径来控制动画的执行快慢,路径可以是贝塞尔曲线,也可以是普通Path。
系统提供的插值器里前面的九个都比较简单,只有最后一个PathInterpolator,是api21添加的新的插值器,而且其有三个构造函数,相对较复杂会单独讲解。
3 插值器的使用
如何使用插值器
xml动画文件,直接指定
XML动画文件使用插值器时,需要设置系统设置的对应的插值器资源ID,上面已给出。
java代码中两种方式:
Java代码使用插值器时,只需创建对应的插值器对象,然后设置给动画对象;也可以加载xml文件中配置的插值器。然后利用view的setInterpolator(Context context, @AnimRes @InterpolatorRes int resID)设置插值器。
xml设置插值器例子:
<?xml version="1.0" encoding="utf-8"?>
<linearInterpolator
xmlns:android="http://schemas.android.com/apk/res/android">
</linearInterpolator>
代码演示插值器
这里只用Translate动画来演示插值器的效果:
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromXDelta="-300"
android:toXDelta="500"
android:fromYDelta="-300"
android:toYDelta="1000"
android:duration="3000"
android:fillBefore="true">
</translate>
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.btn1:
if (imageView.getAnimation() != null && !imageView.getAnimation().hasEnded()){
imageView.getAnimation().cancel();
}
mTranslateAnimation.setInterpolator(new AccelerateInterpolator());
imageView.startAnimation(mTranslateAnimation);
break;
case R.id.btn2:
if (imageView.getAnimation() != null && !imageView.getAnimation().hasEnded()){
imageView.getAnimation().cancel();
}
mTranslateAnimation.setInterpolator(new DecelerateInterpolator());
imageView.startAnimation(mTranslateAnimation);
break;
case R.id.btn3:
if (imageView.getAnimation() != null && !imageView.getAnimation().hasEnded()){
imageView.getAnimation().cancel();
}
mTranslateAnimation.setInterpolator(new AccelerateDecelerateInterpolator());
imageView.startAnimation(mTranslateAnimation);
break;
case R.id.btn4:
if (imageView.getAnimation() != null && !imageView.getAnimation().hasEnded()){
imageView.getAnimation().cancel();
}
mTranslateAnimation.setInterpolator(new LinearInterpolator());
imageView.startAnimation(mTranslateAnimation);
break;
case R.id.btn5:
if (imageView.getAnimation() != null && !imageView.getAnimation().hasEnded()){
imageView.getAnimation().cancel();
}
mTranslateAnimation.setInterpolator(new AnticipateInterpolator());
imageView.startAnimation(mTranslateAnimation);
break;
case R.id.btn6:
if (imageView.getAnimation() != null && !imageView.getAnimation().hasEnded()){
imageView.getAnimation().cancel();
}
mTranslateAnimation.setInterpolator(new OvershootInterpolator());
imageView.startAnimation(mTranslateAnimation);
break;
case R.id.btn7:
if (imageView.getAnimation() != null && !imageView.getAnimation().hasEnded()){
imageView.getAnimation().cancel();
}
mTranslateAnimation.setInterpolator(new AnticipateOvershootInterpolator());
imageView.startAnimation(mTranslateAnimation);
break;
case R.id.btn8:
if (imageView.getAnimation() != null && !imageView.getAnimation().hasEnded()){
imageView.getAnimation().cancel();
}
mTranslateAnimation.setInterpolator(new BounceInterpolator());
imageView.startAnimation(mTranslateAnimation);
break;
case R.id.btn9:
if (imageView.getAnimation() != null && !imageView.getAnimation().hasEnded()){
imageView.getAnimation().cancel();
}
mTranslateAnimation.setInterpolator(new CycleInterpolator(5));
imageView.startAnimation(mTranslateAnimation);
break;
}
}
4 PathInterpolator 路径插值器
作用说明:
路径插值器在动画运行过程中,会遍历整个路径,路径必须从(0,0)开始到(1,1)点结束。它会在一个1*1的坐标系内部指定动画的运动轨迹,路径可以是贝塞尔曲线或者是普通的path。
兼容版本可以用PathInterpolatorCompat类,在v4包中。
构造函数:
PathInterpolator(Path path):利用Path构造插值器。
PathInterpolator(float controlX, float controlY):传入一个控制点,构造二维贝塞尔曲线插值器。
PathInterpolator(float controlX1, float controlY1, float controlX2, float controlY2):传入两个控制点,构造三维贝塞尔曲线插值器。
PathInterpolator(Context context, AttributeSet attrs),加载xml定义的插值器。
其中X坐标轴表示时间进度,动画进行了多长时间,0表示刚开始,1表示动画运行完了。
Y坐标表示动画完成程度,0表示动画初始状态,0.5表示动画完成一半时的状态,1表示动画结束时的状态。
举个例子:
Path path = new Path();
path.lineTo(0.25f, 0.25f);
path.moveTo(0.25f, 0.5f);
path.lineTo(1f, 1f);
解释:上面的代码生成的PathInterpolator得含义为,首先按照动画完成度和时间1:1的比例,在1/4的时间内达到动画完成1/4的效果,然后突然让动画变成完成1/2的状态此时动画运行时间依然才过了1/4,然后在接下来的时间让动画运行到结束,状态也变成动画结束后的状态。所以展示的效果就是先匀速变化,然后突然变化,然后在匀速变化。
示意图:
贝塞尔曲线的应用
PathInterpolator(float controlX, float controlY) 传入一个控制点,这个函数内部会生成贝塞尔曲线,就可以生成对应的插值器。
PathInterpolator pathInterpolator = new PathInterpolator(0.9f, 0.1f);
mTranslateAnimation.setInterpolator(pathInterpolator);
imageView.startAnimation(mTranslateAnimation);
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromXDelta="-300"
android:toXDelta="500"
android:fromYDelta="-300"
android:toYDelta="1000"
android:duration="3000"
android:fillBefore="true">
</translate>
时间与速度变化示意图,从贝塞尔曲线可以看出首先动画变化速度缓慢,然后大概动画运行了80%时快速完成动画。
5 support v4 包中新提供的插值器
FastOutLinearInInterpolator ,FastOutSlowInInterpolator,LinearOutSlowInInterpolator,这三个是在v4 22.1.0中添加的动画插值器,基本原理和PathInterpolator一样,都是利用贝塞尔曲线来描述动画运行过程。
FastOutLinearInInterpolator 效果和AccelerateInterpolator 类似,都是一个持续加速的运动路线,只是刚开始阶段LinearOutSlowInInterpolator更快。
FastOutSlowInInterpolator 是先加速再减速,类似AccelerateDecelerateInterpolator ,但FastOutSlowInInterpolator 前期比AccelerateDecelerateInterpolator 快很多。
LinearOutSlowInInterpolator 和DecelerateInterpolator 的效果类似。
FastOutLinearInInterpolator举例:
FastOutLinearInInterpolator fastOutLinearInInterpolator = new FastOutLinearInInterpolator();
mTranslateAnimation.setInterpolator(fastOutLinearInInterpolator);
imageView.startAnimation(mTranslateAnimation);
Animation动画概述和执行原理
Android动画之补间动画TweenAnimation
Android动画之逐帧动画FrameAnimation
Android动画之插值器简介和系统默认插值器
Android动画之插值器Interpolator自定义
Android动画之视图动画的缺点和属性动画的引入
Android动画之ValueAnimator用法和自定义估值器
Android动画之ObjectAnimator实现补间动画和ObjectAnimator自定义属性
Android动画之ObjectAnimator中ofXX函数全解析-自定义Property,TypeConverter,TypeEvaluator
Android动画之AnimatorSet联合动画用法
Android动画之LayoutTransition布局动画
Android动画之共享元素动画
Android动画之ViewPropertyAnimator(专用于view的属性动画)
Android动画之Activity切换动画overridePendingTransition实现和Theme Xml方式实现
Android动画之ActivityOptionsCompat概述
Android动画之场景变换Transition动画的使用
Android动画之Transition和TransitionManager使用
Android动画之圆形揭露动画Circular Reveal
Android 动画之 LayoutAnimation 动画
Android动画之视图动画的缺点和属性动画的引入