利用属性动画，打造一个重力弹跳的效果

二、实现思路：

    public class GravityEvarlutor implements TypeEvaluator<Integer> {

@Override
public Float evaluate(float fraction, Float startValue, Float endValue) {

}
}

public class GravityEvarlutor implements TypeEvaluator<Integer> {

@Override
public Float evaluate(float fraction, Integer startValue, Integer endValue) {
//_h1为初始下落高度，_h2,_h3,_h4为各次的回弹高度
int _h1 = endValue - startValue;
int _h2 = _h1/7;
int _h3 = _h1/35;
int _h4 = _h1/105;

//根据t = Math.sqrt(2 * h/a)以及t1 + 2*t2 + 2*t3 + 2*t4 = 1，可算出：
double t1 = 1 / 2.28917;

//从而得出重力加速度
double a = (2 * _h1) / (t1 * t1);

//再求出t2,t3,t4
double t2 = Math.sqrt(2 * _h2 / a);
double t3 = Math.sqrt(2 * _h3 / a);
double t4 = Math.sqrt(2 * _h4 / a);

//算出各个时间段的最大速度vt，因为每次在最大高度时满足v = 0，所以在接触地面时，达到最大速度vt = a * t
double vt1 = a * t1;
double vt2 = a * t2;
double vt3 = a * t3;
double vt4 = a * t4;
}
}

    //将fraction进行分段，便于每段独立分析
double fraction2_1 = fraction - t1;
double fraction2_2 = fraction - t1 - t2;
double fraction3_1 = fraction - t1 - (2 * t2);
double fraction3_2 = fraction - t1 - (2 * t2) - t3;
double fraction4_1 = fraction - t1 - (2 * t2) - (2 * t3);
double fraction4_2 = fraction - t1 - (2 * t2) - (2 * t3) - t4;

    //分段算出最终值h
int h = 0;
if(fraction <= t1) {
h = (int)(_h1 - a * 0.5 * fraction * fraction);
}else if(fraction > t1 && fraction <= (t1 + t2)){//2-1
h = (int)(vt2 * fraction2_1 - a * 0.5 * fraction2_1 * fraction2_1);
}else if(fraction > (t1 + t2) && fraction <= (t1 + (2 * t2))){//2-2
h = (int)(_h2 - a * 0.5 * fraction2_2 * fraction2_2);
}else if(fraction > (t1 + (2 * t2)) && fraction <= (t1 + (2 * t2) + t3)){//3-1
h = (int)(vt3 * fraction3_1 - a * 0.5 * fraction3_1 * fraction3_1);
}else if(fraction > (t1 + (2 * t2) + t3) && fraction <= (t1 + (2 * t2) + (2 * t3))){//3-2
h = (int)(_h3 - a * 0.5 * fraction3_2 * fraction3_2);
}else if(fraction > (t1 + (2 * t2) + (2 * t3))&& fraction <= (t1 + (2 * t2) + (2 * t3) + t4)){//4-1
h = (int)(vt4 * fraction4_1 - a * 0.5 * fraction4_1 * fraction4_1);
}else{//4-2
h = (int)(_h4 - a * 0.5 * fraction4_2 * fraction4_2);
}

ok，大功告成，但是有个小问题，因为我们算出来的值为double类型，强转成int后会有偏差，因此最后我们需要做下偏差矫正：

    if(fraction == 1){
h = 0;
}

public class GravityEvarlutor implements TypeEvaluator<Integer> {

/**
* 因为fraction是从0~1，因此我们可以将总时长看成1
* @param fraction
* @param startValue
* @param endValue
* @return
*/
@Override
public Integer evaluate(float fraction, Integer startValue, Integer endValue) {

//_h1为初始下落高度，_h2,_h3,_h4为各次的回弹高度
int _h1 = endValue - startValue;
int _h2 = _h1/7;
int _h3 = _h1/35;
int _h4 = _h1/105;

//根据t = Math.sqrt(2 * h/a)以及t1 + 2*t2 + 2*t3 + 2*t4 = 1，可算出：
double t1 = 1 / 2.28917;

//从而得出重力加速度
double a = (2 * _h1) / (t1 * t1);

//再求出t2,t3,t4
double t2 = Math.sqrt(2 * _h2 / a);
double t3 = Math.sqrt(2 * _h3 / a);
double t4 = Math.sqrt(2 * _h4 / a);

//算出各个时间段的最大速度vt，因为每次在最大高度时满足v = 0，所以在接触地面时，达到最大速度vt = a * t
double vt1 = a * t1;
double vt2 = a * t2;
double vt3 = a * t3;
double vt4 = a * t4;

//将fraction进行分段，便于每段独立分析
double fraction2_1 = fraction - t1;
double fraction2_2 = fraction - t1 - t2;
double fraction3_1 = fraction - t1 - (2 * t2);
double fraction3_2 = fraction - t1 - (2 * t2) - t3;
double fraction4_1 = fraction - t1 - (2 * t2) - (2 * t3);
double fraction4_2 = fraction - t1 - (2 * t2) - (2 * t3) - t4;

//分段算出最终值h
int h = 0;
if(fraction <= t1) {
h = (int)(_h1 - a * 0.5 * fraction * fraction);
}else if(fraction > t1 && fraction <= (t1 + t2)){//2-1
h = (int)(vt2 * fraction2_1 - a * 0.5 * fraction2_1 * fraction2_1);
}else if(fraction > (t1 + t2) && fraction <= (t1 + (2 * t2))){//2-2
h = (int)(_h2 - a * 0.5 * fraction2_2 * fraction2_2);
}else if(fraction > (t1 + (2 * t2)) && fraction <= (t1 + (2 * t2) + t3)){//3-1
h = (int)(vt3 * fraction3_1 - a * 0.5 * fraction3_1 * fraction3_1);
}else if(fraction > (t1 + (2 * t2) + t3) && fraction <= (t1 + (2 * t2) + (2 * t3))){//3-2
h = (int)(_h3 - a * 0.5 * fraction3_2 * fraction3_2);
}else if(fraction > (t1 + (2 * t2) + (2 * t3))&& fraction <= (t1 + (2 * t2) + (2 * t3) + t4)){//4-1
h = (int)(vt4 * fraction4_1 - a * 0.5 * fraction4_1 * fraction4_1);
}else{//4-2
h = (int)(_h4 - a * 0.5 * fraction4_2 * fraction4_2);
}
if(fraction == 1){
h = 0;
}
return h;
}
}

public void play(View v){
ValueAnimator va = ValueAnimator.ofObject(new GravityEvarlutor(), 0, layout_main.getHeight() - btn_play.getHeight() - ball.getHeight());
@Override
public void onAnimationUpdate(ValueAnimator animation) {
ball.setY(layout_main.getHeight() - btn_play.getHeight() - ball.getHeight() - (Integer) animation.getAnimatedValue());
}
});
va.setDuration(800);
va.setInterpolator(new LinearInterpolator());
va.start();
}

animate.css源码分析--bounce(弹跳效果)

2016-11-09 20:09:10

简单的弹跳动画

2012-12-19 16:14:05

彩色球屏保

2017-01-17 00:47:37

安卓动画系列之一,妙用Interpolator 快速实现弹球效果

2015-01-27 20:58:22

安卓垂直抖动动画，实现小球掉落弹起效果

2016-07-25 15:08:04

Android 属性动画：这是一篇很详细的 属性动画 总结&攻略

2017-06-08 09:00:28

Android属性动画完全解析(中)，ValueAnimator和ObjectAnimator的高级用法

2015-05-07 09:04:32

Android属性动画完全解析(上)，初识属性动画的基本用法

2015-04-09 09:56:15

Android补间动画之alpha、scale、translate、rotate、set详解

2017-08-15 14:15:11

安卓动画知识总结 Animation AnimationSet LayoutAnimation

2014-09-04 21:20:46