在洋神的公众号上看了一位作者的尺子控件,后来down了一下源码,发现有一个比较有趣的地方就是,惯性动画;即当手指快速向左或者向右滑动,并抬起之后,有一个惯性产生,使view再持续一段时间去绘制,并且逐渐递减的停下来,其实这个动画也不新鲜,像RV上下滑动,很经典,看了一下作者的思路,决定把之前写的自定义的K线View加上这个动画,并在此整理做一下笔记,这里非常感谢作者提供的思路,谢谢 !!
先看看这个惯性动画的原理:
对,没错,就是它:VelocityTracker
VelocityTracker
是一个跟踪触摸事件滑动速度的帮助类,用于实现flinging以及其它类似的手势。它的原理是把触摸事件 MotionEvent 对象传递给VelocityTracker的addMovement(MotionEvent)方法,然后分析MotionEvent 对象在单位时间类发生的位移来计算速度。你可以使用getXVelocity() 或getXVelocity()获得横向和竖向的速率到速率时,但是使用它们之前请先调用computeCurrentVelocity(int)来初始化速率的单位 。使用方法
- 使用 VelocityTracker.obtain() 初始化,得到它的对象
- addMovement(ev),将事件的MotionEvent添加进去
- 调用computeCurrentVelocity,它有两个重载方法
intunitis表示速率的基本时间单位。unitis值为1的表示是,一毫秒时间单位内运动了多少个像素, unitis值为1000表示一秒(1000毫秒)时间单位内运动了多少个像素;floatVelocity表示速率的最大值 - getXVelocity和getYVelocity分别表示X轴和Y轴方向上的速率
- 核心代码
@Override
public boolean onTouchEvent(MotionEvent event) {
if (null == velocityTracker) {
velocityTracker = VelocityTracker.obtain();//手指抬起之后的速度变化
}
velocityTracker.computeCurrentVelocity(200);
velocityTracker.addMovement(event);
//在MotionEvent.ACTION_UP回调中获取抬手之后的移动速率
xVelocity = (int) velocityTracker.getXVelocity();
通过属性动画去处理
核心思想就是在抬手瞬间的初始速度Velocity ,随着时间的推迟,慢慢减小为零,那么这段变化内就能够拿到变化因子,这个变化因子与当前距离或者其他因素在一起,共同完成了这一套优美的动画
@Override
protected void setxVelocity(int xVelocity) {
super.setxVelocity(xVelocity);
if (Math.abs(xVelocity) < 50) {
return;
}
if (valueAnimator.isRunning()) {
return;
}
valueAnimator = ValueAnimator.ofInt(0, xVelocity / 20).setDuration(Math.abs(xVelocity / 10));
valueAnimator.setInterpolator(new DecelerateInterpolator());
valueAnimator.addUpdateListener(animation -> {
scrollVelocity = (int) animation.getAnimatedValue();
compuXScroll(-scrollVelocity);
postInvalidate();
});
valueAnimator.start();
valueAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
postInvalidate();
}
});
}
上面这段代码中,速度从初始抬手的xVelocity ,在(xVelocity / 10)毫秒内变化为零,得到scrollVelocity 这个因子,即我快速滑动抬手之后的瞬间速度到速度为0,这个因子和当前曲线绘制结合,使曲线能够在我抬手之后能继续绘制一小段
动画效果