在自定义view的时候,我们通常通过重写他的onTouch(View v, MotionEvent event)方法,我们可以处理一些touch事件,但是对于一些比较复杂的手势,我们如果自己去通过MotionEvent来自己判断的话会有一些复杂和不准确,所以Android为我们提供了GestureDector类来方便我们进行手势的监听处理.
GestureDector为我们提供了两个接口和一个静态外部类供我们去使用,分别是两个接口:OnGestureListener,OnDoubleTapListener,一个静态外部类:SimpleGestureListener.
我们先看一下OnGestureListener这个接口,下面我们看下implements这个接口的代码:
private class gestureListener implements GestureDetector.OnGestureListener{
// 用户轻触触摸屏,由1个MotionEvent ACTION_DOWN触发
public boolean onDown(MotionEvent e) {
Log.i("MyGesture", "onDown");
Toast.makeText(MainActivity.this, "onDown", Toast.LENGTH_SHORT).show();
return false;
}
/*
* 用户轻触触摸屏,尚未松开或拖动,由一个1个MotionEvent ACTION_DOWN触发
* 注意和onDown()的区别,强调的是没有松开或者拖动的状态
*
* 而onDown也是由一个MotionEventACTION_DOWN触发的,但是他没有任何限制,
* 也就是说当用户点击的时候,首先MotionEventACTION_DOWN,onDown就会执行,
* 如果在按下的瞬间没有松开或者是拖动的时候onShowPress就会执行,如果是按下的时间超过瞬间
* (这块我也不太清楚瞬间的时间差是多少,一般情况下都会执行onShowPress),拖动了,就不执行onShowPress。
*/
public void onShowPress(MotionEvent e) {
Log.i("MyGesture", "onShowPress");
Toast.makeText(MainActivity.this, "onShowPress", Toast.LENGTH_SHORT).show();
}
// 用户(轻触触摸屏后)松开,由一个1个MotionEvent ACTION_UP触发
///轻击一下屏幕,立刻抬起来,才会有这个触发
//从名子也可以看出,一次单独的轻击抬起操作,当然,如果除了Down以外还有其它操作,那就不再算是Single操作了,所以这个事件 就不再响应
public boolean onSingleTapUp(MotionEvent e) {
Log.i("MyGesture", "onSingleTapUp");
Toast.makeText(MainActivity.this, "onSingleTapUp", Toast.LENGTH_SHORT).show();
return true;
}
// 用户按下触摸屏,并拖动,由1个MotionEvent ACTION_DOWN, 多个ACTION_MOVE触发
public boolean onScroll(MotionEvent e1, MotionEvent e2,
float distanceX, float distanceY) {
Log.i("MyGesture22", "onScroll:"+(e2.getX()-e1.getX()) +" "+distanceX);
Toast.makeText(MainActivity.this, "onScroll", Toast.LENGTH_LONG).show();
return true;
}
// 用户长按触摸屏,由多个MotionEvent ACTION_DOWN触发
public void onLongPress(MotionEvent e) {
Log.i("MyGesture", "onLongPress");
Toast.makeText(MainActivity.this, "onLongPress", Toast.LENGTH_LONG).show();
}
// 用户按下触摸屏、快速移动后松开,由1个MotionEvent ACTION_DOWN, 多个ACTION_MOVE, 1个ACTION_UP触发
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {
Log.i("MyGesture", "onFling");
Toast.makeText(MainActivity.this, "onFling", Toast.LENGTH_LONG).show();
return true;
}
};
我们看到需要我们重写6个函数,下面我们分别看一下各个函数的调用顺序及特点:
1.onDown(MotionEvent e):用户按下屏幕就会触发.
2.onShowPress(MotionEvent e):如果用户按下屏幕后没有立即松开或拖动会调用此方法,事件调用顺序为onDown--->onShowPress.
3.onLongPress(MotionEvent e):如果用户按下屏幕后没有松开或拖动会调用此方法,事件调用顺序为onDown-->onShowPress-->onLongPress.
4.onSingleTapUp(MotionEvent e):如果用户按下屏幕后立即松开会调用此方法,如果按下之后还有其他操作没有立即松开则不会调用此操作(顾名思义:简单的点击一下,也就意味着没有其他多余的操作才会触发),如果点击一下快速抬起则事件调用顺序为onDown-->onSingleTapUp-->onSingleTapUpConfirmed,如果稍微慢点点击抬起则事件调用顺序为onDown-->onShowPress-->onSingleTapUp-->onSingleTapUpConfirmed.
5.onFling(MotionEvent e1, MotionEvent e2, float velocityX,float velocityY):用户按下屏幕后手指在屏幕上滑动会会调用此方法,但是一次滑动事件仅会调用一次.onFling()的四个参数分别为e1---第一个ACTION_DOWN的motionEvent,e2--第二个ACTION_UP的motionEvent,velocityX--X轴上的手指滑动速度,像素/秒,velocityY--Y轴上的手指滑动速度,像素/秒.事件调用顺序为onDown-->onScroll-->onScroll-->......-->onFling.
6.onScroll(MotionEvent e1, MotionEvent e2,float distanceX, float distanceY):用户按下屏幕后手指在屏幕上滑动会调用此方法,与onFling的区别是在一个滑动事件中onScroll会调用多次,参数中的后两个为滑动的距离而不是滑动的速度.onScroll的四个参数分别为e1---第一个ACTION_DOWN的motionEvent,e2--第二个ACTION_UP的motionEvent,distanceX--在X轴上滑动距离,distanceY--在Y轴上的滑动距离.事件调用顺序为onDown-->onScroll-->onScroll-->......-->onFling.
接下来看一下OnDoubleTapListener这个接口,下面是我们实现OnDoubleTapListener的代码:
private class onDoubleTapListener implements
GestureDetector.OnDoubleTapListener {
/*
* 用来判定该次点击是SingleTap而不是DoubleTap,如果连续点击两次就是DoubleTap手势,如果只点击一次,
* 系统等待一段时间后没有收到第二次点击则判定该次点击为SingleTap而不是DoubleTap,
* 然后触发SingleTapConfirmed事件。
*/
@Override
public boolean onSingleTapConfirmed(MotionEvent e) {
// TODO Auto-generated method stub
return false;
}
/*双击事件
*/
@Override
public boolean onDoubleTap(MotionEvent e) {
// TODO Auto-generated method stub
return false;
}
/*
* 双击间隔中发生的动作。指触发onDoubleTap以后,在双击之间发生的其它动作,包含down、up和move事件
* @MotionEvent e中包含了双击直接发生的其他动作.
*/
@Override
public boolean onDoubleTapEvent(MotionEvent e) {
// TODO Auto-generated method stub
return false;
}
}
我们看到要重写3个函数,我们来分别看一下各个函数的调用时间及特点:
1.onSingleTapConfirmed():当用户按下屏幕后并快速抬起时调用并在之后短时间没有二次点击,主要是用来确认用户该次点击是onSingleTap而不是onDoubleTap.事件调用顺序为:onDownn-->onSingleTap-->onSingleTapConfirmed.
2.onDoubleTap():当用户双击屏幕时调用,如果用户触发了onDoubleTap则不会触发onSingleTapConfirmed.该事件调用顺序为:ondown-->onSingleTap-->onDoubleTap().
3.onDoubleTapEvent():当用户双击屏幕间,触发的触摸事件,包含down,up和move事件,事件封装在参数MotionEvent e中.
最后我们看一下SimpleGestureListener静态外部类,代码如下
private class simpleGestureListener extends GestureDetector.SimpleOnGestureListener{
@Override
public boolean onSingleTapUp(MotionEvent e) {
// TODO Auto-generated method stub
return super.onSingleTapUp(e);
}
@Override
public void onLongPress(MotionEvent e) {
// TODO Auto-generated method stub
super.onLongPress(e);
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2,
float distanceX, float distanceY) {
// TODO Auto-generated method stub
return super.onScroll(e1, e2, distanceX, distanceY);
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {
// TODO Auto-generated method stub
return super.onFling(e1, e2, velocityX, velocityY);
}
@Override
public void onShowPress(MotionEvent e) {
// TODO Auto-generated method stub
super.onShowPress(e);
}
@Override
public boolean onDown(MotionEvent e) {
// TODO Auto-generated method stub
return super.onDown(e);
}
@Override
public boolean onDoubleTap(MotionEvent e) {
// TODO Auto-generated method stub
return super.onDoubleTap(e);
}
@Override
public boolean onDoubleTapEvent(MotionEvent e) {
// TODO Auto-generated method stub
return super.onDoubleTapEvent(e);
}
@Override
public boolean onSingleTapConfirmed(MotionEvent e) {
// TODO Auto-generated method stub
return super.onSingleTapConfirmed(e);
}
}
基本就把我们之前介绍的7个方法拼在一起,并没有什么特别的地方,所以我们就看下GestureDector如何使用.
GestureDector的使用分为3步
1.新建一个GestureDector对象
GestureDetector mGestureDetector = new GestureDetector(new gestureListener());
2.实例化一个GestureDetector.OnGestureListener通过我们上面的三种方法
3.在onTouch()事件中声明将触摸事件交给GestureDector处理
/*
* 在onTouch()方法中,我们调用GestureDetector的onTouchEvent()方法,
* 将捕捉到的MotionEvent交给GestureDetector 来分析是否有合适的callback函数来处理用户的手势
*/
@Override
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
return mGestureDetector.onTouchEvent(event);
}