VelocityTracker的用法、原理与场景使用场景
一. 基本使用
VelocityTracker是Android系统提供的用于追踪手指滑动速度的类,包括水平方向和垂直方向,
// 获取tracker对象
VelocityTracker velocityTracker= VelocityTracker.obtain() ;
// 添加监听对象,一般是MotionEvent
velocityTracker.addMovement(event);
// 设置时间单位,units:设置为1,表示1毫秒时间单位内运动了多少个像素;
// 设置为1000,表示1秒时间单位内运动了多少个像素。
velocityTracker.computeCurrentVelocity(int units,float maxVelocity);
// 获取x方向(水平)的速度
int xVelocity = (int) velocityTracker.getXVelocity();
// 获取Y方向(垂直)的速度
int yVelocity = (int) velocityTracker.getYVelocity();
// 在手指抬起(ACTION_UP)或者事件取消(ACTION_CANCEL)的时候,调用下面的函数
recycle();
二. 常见使用场景
场景1:Fling效果,典型应用如RecyclerView,GestureDetector
RecyclerView.java
@Override
public boolean onTouchEvent(MotionEvent e) {
....
if (mVelocityTracker == null) {
mVelocityTracker = VelocityTracker.obtain();
}
boolean eventAddedToVelocityTracker = false;
switch (action) {
case MotionEvent.ACTION_DOWN: {
......
mScrollPointerId = e.getPointerId(0);
......
}
break;
case MotionEvent.ACTION_MOVE: {
......
break;
case MotionEvent.ACTION_UP: {
mVelocityTracker.addMovement(vtev);
eventAddedToVelocityTracker = true;
mVelocityTracker.computeCurrentVelocity(1000, mMaxFlingVelocity);
// 计算手指滑动 X/Y方向上的速度
final float xvel = canScrollHorizontally
? -mVelocityTracker.getXVelocity(mScrollPointerId) : 0;
final float yvel = canScrollVertically
? -mVelocityTracker.getYVelocity(mScrollPointerId) : 0;
// 使用X、Y方向上的速度,计算fling的距离
if (!((xvel != 0 || yvel != 0) && fling((int) xvel, (int) yvel))) {
setScrollState(SCROLL_STATE_IDLE);
}
resetScroll();
}
break;
case MotionEvent.ACTION_CANCEL: {
cancelScroll();
}
break;
}
if (!eventAddedToVelocityTracker) {
mVelocityTracker.addMovement(vtev);
}
vtev.recycle();
return true;
}
三. 实现原理
我们从该类最关键的两个函数computeCurrentVelocity()和getVelocity(getXVelocity和getXVelocity底层调用的是此函数)着手分析下.
/**
* Compute the current velocity based on the points that have been
* collected. Only call this when you actually want to retrieve velocity
* information, as it is relatively expensive. You can then retrieve
* the velocity with {@link #getXVelocity()} and
* {@link #getYVelocity()}.
*
* @param units The units you would like the velocity in. A value of 1
* provides pixels per millisecond, 1000 provides pixels per second, etc.
* @param maxVelocity The maximum velocity that can be computed by this method.
* This value must be declared in the same unit as the units parameter. This value
* must be positive.
*/
public void computeCurrentVelocity(int units, float maxVelocity) {
nativeComputeCurrentVelocity(mPtr, units, maxVelocity);
}
/**
* Retrieve the last computed X velocity. You must first call
* {@link #computeCurrentVelocity(int)} before calling this function.
*
* @param id Which pointer's velocity to return.
* @return The previously computed X velocity.
*/
public float getXVelocity(int id) {
return nativeGetXVelocity(mPtr, id);
}
/**
* Retrieve the last computed Y velocity. You must first call
* {@link #computeCurrentVelocity(int)} before calling this function.
*
* @param id Which pointer's velocity to return.
* @return The previously computed Y velocity.
*/
public float getYVelocity(int id) {
return nativeGetYVelocity(mPtr, id);
}
调用的是JNI层文件实现具体功能,