Android提供了一些工具类,以便于快速判断手势事件的类型和进行相关处理。例如各种动作的判断(双击、长按等),例如计算滑动速度。这些当然可以在onTouchEvent(MotionEvent)中自己写逻辑进行处理,但借助工具类更简便。
1.手势检测器GestureDetector,可用于判断各种手势,双击、长按等。
示例代码和注释如下:
// 步骤1.创建一个监听回调
GestureDetector.SimpleOnGestureListener listener = new GestureDetector.SimpleOnGestureListener() {
/*常用的回调方法*/
//单击
@Override
public boolean onSingleTapConfirmed(MotionEvent e) {
//......业务逻辑......
return false;
}
//双击
@Override
public boolean onDoubleTap(MotionEvent e) {
//......业务逻辑......
return false;
}
//长按
@Override
public void onLongPress(MotionEvent e) {
//......业务逻辑......
}
//滚动
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
//......业务逻辑......
return false;
}
//快速滑动
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
//......业务逻辑......
return false;
}
};
// 步骤2.创建一个检测器
final GestureDetector detector = new GestureDetector(this, listener);
//解决长按屏幕后无法拖动的问题(这行是《Android开发艺术探索》中建议)
detector.setIsLongpressEnabled(false);
// 步骤3.将事件对象传递给手势检测器GestureDetector。
// 可以在外部setOnTouchListener来获取MotionEvent对象,可在View类自己的onTouchEvent()中获取。
mTvTop.setOnTouchListener(new View.OnTouchListener() {
@Override public boolean onTouch(View v, MotionEvent event) {
//《Android开发艺术探索》中的建议是:
//双击这类事件用GestureDetector来判断;
//滑动这类事件结合MotionEvent的action类型,自己写逻辑来判断,。
return detector.onTouchEvent(event);
}
});
2.滑动速度检测:VelocityTracker(用于滑动速度检测)
简单原理:监测指定时间内,某个触摸点在x轴、y轴上滑动的像素数,正向滑动时,为正值;反向滑动时,为负值。
附:可通过ViewConfiguration来获取系统中一系列滑动相关的参数,例如能够触发滑动事件的最小滑动距离,系统中的最大滑动速率等。
VelocityTracker示例代码和注释如下:
public class VelocityTrackerActivity extends Activity {
private VelocityTracker mVelocityTracker;
private int mMaxVelocity;
private int mPointerId;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mVelocityTracker = VelocityTracker.obtain();//步骤1:创建检测器对象
//获取设备支持的最大滑动速率,单位:像素/s
mMaxVelocity = ViewConfiguration.get(this).getMaximumFlingVelocity();
//获取系统能够识别出的最小滑动距离,即 能够触发系统滑动事件的最小滑动距离。
//有时候用户的手指在点击时有轻微的抖动,发生了极微小的距离,这时候用户并想滑动,也许只是想点击
//如何区分用户是否想滑动呢,建议用系统给的这个值来判断,在不同的设备上这个值有时候是不同的。
int touchSlop = ViewConfiguration.get(this).getScaledTouchSlop();
}
@Override
public boolean onTouchEvent(MotionEvent event) {
final int action = event.getAction();
mVelocityTracker.addMovement(event);//步骤2:添加被检测的事件
final VelocityTracker verTracker = mVelocityTracker;
switch (action) {
case MotionEvent.ACTION_DOWN:
//此时可能有多个触点,此处监控第一个触点的滑动速度
mPointerId = event.getPointerId(0);
break;
case MotionEvent.ACTION_MOVE:
//步骤3:指定时间内的滑动的像素数距离(正向滑动时,为正值;反向滑动时,为负值。)
//此处设定本次监测的时间长度,单位ms
//第二个参数值作用:当滑动速率大于第二个参数值时,将以第二个参数值来作为速率。
verTracker.computeCurrentVelocity(1000, mMaxVelocity);
//获取指定时间内,水平滑动、数值滑动的像素距离
float velocityX = verTracker.getXVelocity(mPointerId);
float velocityY = verTracker.getYVelocity(mPointerId);
//计算滑动速度,单位:像素/s
float speedX = velocityX;
float speedY = velocityY;
break;
case MotionEvent.ACTION_UP:
releaseVelocityTracker();//步骤4:监听结束后,释放监听器对象
break;
case MotionEvent.ACTION_CANCEL:
releaseVelocityTracker();//步骤4:监听结束后,释放监听器对象
break;
default:
break;
}
return super.onTouchEvent(event);
}
//释放VelocityTracker
private void releaseVelocityTracker() {
if(null != mVelocityTracker) {
mVelocityTracker.clear();
mVelocityTracker.recycle();
mVelocityTracker = null;
}
}
}