这篇文章用来讲解,如何跟踪touch event的轨迹。
onTouchEvent()方法 由 ACTION_MOVE 事件触发(只要当前的接触的 position, pressure,size发生了变化)。 就像上一篇文章 Detecting Common Gestures讲到的一样,这些event会被记录在MotionEvent中,而这个MotionEvent将作为onTouchEvent()的参数。
用户交互中基于手指触碰的反馈往往都不是最精确的,所以 监测 touch event的时候 用 movement(移动)来判定 比 simple contact(简单的接触)用的更多。
为了 帮助app来辨别 (movement-based gestures)移动类型的手势【例如 swipe 滑动,擦除,】和(nonmovement-based gestures )非移动类型的手势【例如 single tap 单击】。Android提出了一个概念,”touch slop“。 Touch slop用来表明一个用户手指移动的界限,这个界限用来判定这个 手势 是移动类型的手势,还是非移动类型的手势。(这个界限的单位 是pixels 像素)。
换句话说 就是:如果 用户的手指触碰屏幕之后,移动的距离超过了界限,那么判定为 移动类型的手势,如果没有超过界限,则判定为 非移动类型的手势。详细可见
Managing Touch Events in a ViewGroup.
这里有几种不同的方式来跟踪 手势的移动轨迹,根据你的app的需求可以自己选择。
*1.起点和终点(从屏幕的A点移动到B点)
*2.点移动的方向(由x,y共同决定)
*3.历史,你可以通过MotionEvent中的getHistorySize()方法来 找到你的历史手势的size。你也可以通过getHistorical< Value >方法获取 其他的信息 例如 postions,sizes,time,pressures 。
在手机渲染你的手指移动轨迹的时候 历史信息是非常有用的,特别是一些 通过手指画画的应用。 详情可以看 MotionEvent
*4.点在屏幕上移动的速率
Track Velocity
你可能以为 移动类型的手势 都是通过 点移动的距离,或者方向来触发的。其实 速率 也是手势的一个重要的特性,也是决定一个手势能否触发的重要因素。
为了使计算更简单,Android提供了 VelocityTracker类,和 VelocityTrackerCompat类(在Support Library. VelocityTracker)来帮助你 跟踪 touch event的速率。那些用到了 Velocity(速率)的手势是非常有用的,比如 fling(抛掷手势)
下面就是一个简单的使用 VelocityTracker的例子。
public class MainActivity extends Activity {
private static final String DEBUG_TAG = "Velocity";
...
private VelocityTracker mVelocityTracker = null;
@Override
public boolean onTouchEvent(MotionEvent event) {
int index = event.getActionIndex();
int action = event.getActionMasked();
int pointerId = event.getPointerId(index);
switch(action) {
case MotionEvent.ACTION_DOWN:
if(mVelocityTracker == null) {
// Retrieve a new VelocityTracker object to watch the velocity of a motion.
mVelocityTracker = VelocityTracker.obtain();
}
else {
// Reset the velocity tracker back to its initial state.
mVelocityTracker.clear();
}
// Add a user‘s movement to the tracker.
mVelocityTracker.addMovement(event);
break;
case MotionEvent.ACTION_MOVE:
mVelocityTracker.addMovement(event);
// When you want to determine the velocity, call
// computeCurrentVelocity(). Then call getXVelocity()
// and getYVelocity() to retrieve the velocity for each pointer ID.
mVelocityTracker.computeCurrentVelocity(1000);
// Log velocity of pixels per second
// Best practice to use VelocityTrackerCompat where possible.
Log.d("", "X velocity: " +
VelocityTrackerCompat.getXVelocity(mVelocityTracker,
pointerId));
Log.d("", "Y velocity: " +
VelocityTrackerCompat.getYVelocity(mVelocityTracker,
pointerId));
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
// Return a VelocityTracker object back to be re-used by others.
mVelocityTracker.recycle();
break;
}
return true;
}
}
注意 :
最后要注意的一点是:你应该在ACTION_MOVE事件中计算速率,而不是在ACTION_UP之后。在ACTION_UP之后,x,和 y的速率会变为0;