文章目录
- 1. 插值器
- 2. 估值器
1. 插值器
插值器是在 XML 中定义的动画修改器,它会 影响动画的变化速率。插值器可对现有的动画效果执行加速、减速、重复、退回等
插值器通过 android:interpolator
属性应用于动画元素,该属性的值是对插值器资源的引用
Android默认提供了9个插值器供使用:
- AccelerateDecelerateInterpolator:变化率在开始和结束时缓慢,但在中间会加快
- AccelerateInterpolator:变化率在开始时较为缓慢,然后会加快
- AnticipateInterpolator:先反向变化,然后再急速正向变化
- AnticipateOvershootInterpolator:先反向变化,再急速正向变化并超过目标值,然后以最终值结束
- BounceInterpolator:变化会在结束时退回
- CycleInterpolator:按指定的循环次数重复动画。变化率符合正弦曲线图
- DecelerateInterpolator:变化率开始时很快,然后减慢
- LinearInterpolator:变化率恒定不变
- OvershootInterpolator:先急速正向变化,再超过最终值,然后回到最终值
- TimeInterpolator:该接口用于实现自定义的插值器
原理说明:
public interface TimeInterpolator{
float getInterpolator(float input);
}
当前动画开始后,View
会周期性调用它的getTransformation
方法不断获得动画结果,方法返回表示的是当前动画是否结束
// Animation.java
public boolean getTransformation(long currentTime, Transformation outTransformation){
//...
if ((normalizedTime >= 0.0f || mFillBefore) && (normalizedTime <= 1.0f || mFillAfter)) {
//...
// 插值器
final float interpolatedTime = mInterpolator.getInterpolation(normalizedTime);
// 子类完成实际的动画逻辑
applyTransformation(interpolatedTime, outTransformation);
}
}
Transformation
:包含Matrix和Alpha字段,用来记录某次动画计算的变换结果
// ViewGroup.java
Transformation getChildTransformation() {
if (mChildTransformation == null) {
mChildTransformation = new Transformation();
}
return mChildTransformation;
}
调用栈追溯
// View.java
boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) {
//...
final Animation a = getAnimation();
if (a != null) {
more = applyLegacyAnimation(parent, drawingTime, a, scalingRequired);
//...
}
}
private boolean applyLegacyAnimation(ViewGroup parent, long drawingTime,
Animation a, boolean scalingRequired) {
//...
final Transformation t = parent.getChildTransformation();
boolean more = a.getTransformation(drawingTime, t, 1f);
//...
}
属性动画 ValueAnimator
// ValueAnimator.java
void animateValue(float fraction){
// 插值器
fraction = mInterpolator.getInterpolation(fraction);
//...
}
2. 估值器
public interface TypeEvaluator<T> {
public T evaluate(float fraction, T startValue, T endValue);
}
将 插值器 的返回值转换成我们需要的值,设置属性值从初始值过渡到结束值变化的具体数值,可以理解为运动轨迹的表现
public class PointView{
public float x;
public float y;
}
自定义一个TypeEvaluator
class PointViewEvaluator implements TypeEvaluator{
@Override
public Object evaluate(float fraction, Object startValue, Object endValue){
PointView pv = new PointView();
pv.x = 400*(fraction*2);
pv.y = 400*Math.pow(fraction*2,2);
}
}
另外我们将时间写死了为2s。自定义好之后我们就可以直接拿过来用了代码如下
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private ImageView ivBall;
private Button btnClick;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ivBall=findViewById(R.id.iv_ball);
btnClick=findViewById(R.id.btn_click);
btnClick.setOnClickListener(this);
}
@Override
public void onClick(View view) {
ValueAnimator valueAnimator=ValueAnimator.ofObject(new PointViewEvaluator(),new PointView(0,0));
valueAnimator.setDuration(2000);
valueAnimator.setInterpolator(new LinearInterpolator());
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
//获取ValueAnimator在运动时,当前运动点的值
PointView pointView= (PointView) valueAnimator.getAnimatedValue();
ivBall.setX(pointView.x);
ivBall.setY(pointView.y);
}
});
valueAnimator.start();
}
}
运行之后可发现,上述动画轨迹是匀速执行的抛物线运动。通过以上例子我们可以感受估值器的作用是什么样的。