13.1.1 概述
GestureDetector,手势检测类,通过这个类可以识别很多手势。在识别出手势之后,具体的事物处理则交由程序员自己来实现。
此类提供了两个接口(OnGestureListener、OnDoubleTapListener)和一个外部类(SimpleOnGestureListener)。这个外部类其实是两个接口中所有函数的集成,它包含了这两个接口里所有必须实现的函数,而且都已经被重写,但所有函数体都是空的。该类是一个静态类,程序员可以在外部继承这个类,重写里面的手势处理函数。
13.1.2 GestureDetector.OnGestureListener 接口
1. 基本讲解
如果我们写一个类并继承自 OnGestureListener,则会提示有几个必须重写的函数。代码如下:
这些函数在什么情况下才会被触发呢?
- onDown(MotionEvent e):用户按下屏幕就会触发该函数。
- onShowPress(MotionEvent e):如果按下的时间超过瞬间,而且在按下的时候没有松开或者是拖动的,该函数就会被触发。
- onLongPress(MotionEvent e):长按触摸屏,超过一定时长,就会触发这个函数。
触发顺序:
- onSingleTapUp(MotionEvent e):一次单独的轻击抬起操作,也就是轻击一下屏幕,立刻抬起来,才会触发这个函数。当然,如果除 down 以外还有其他操作,就不再算是单独操作了,也就不会触发这个函数。
单击一下非常快的(不滑动)Touchup,触发顺序:
单击一下稍微慢一点的(不滑动)Touchup,触发顺序:
- onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY):滑屏,用户按下触摸屏、快速移动后松开,由一个 MotionEvent ACTION_DOWN、多个 ACTION_MOVE、一个 ACTION_UP 触发。
- onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY):在屏幕上拖动事件。无论是用手拖动 View,还是以抛的动作滚动,都会多次触发这个函数,在 ACTION_MOVE 动作发生时就会触发该函数。
滑屏,即手指出动屏幕后,稍微滑动后立即松开,触发顺序为:
拖动,触发顺序为:
可见,无论是滑屏还是拖动,影响的只是中间 onScroll 被触发的数量而已,最终都会触发 onFling 事件。
2. 示例
要使用 GestureDetector,有四步要走。
1)创建 OnGestureListener() 监听函数。
2)创建 GestureDetector 实例 mGestureDetector。
构造函数有以下几个,根据需要选择即可。
3)在 onTouch(View v, MotionEvent event) 中进行拦截。
4)绑定控件。
完整代码如下:
13.1.3 GestureDetector.OnDoubleTapListener 接口
1. 构建
有两种方式设置双击监听。
方法一:新建一个类,同时派生自 OnGestureListener 和 OnDoubleTapListener。
方法二:
使用 GestureDetector.setOnDoubleTapListener() 函数设置双击监听。
无论方法一还是方法二,都需要派生自 GestureDetector.OnGestureListener。
2. 函数讲解
先来看下 OnDoubleTapListener 接口必须重写的三个函数。
- onSingleTapConfirmed(MotionEvent e):单击事件,用来判定该次单击是 SingleTap,而不是 DoubleTap。如果连续单击两次,就是 DoubleTap 手势;如果只单击一次,系统等待一段时间后没有收到第二次单击,则判定该次单击为 SingleTap,而不是 DoubleTap,然后触发 SingleTapConfirm 事件。触发顺序是:onDown —> onSingleTapUp —> onSingleTapConfirmed。有这样一个函数 onSingleTapUp(),它和 onSingleTapConfirmed() 函数容易混淆。二者的区别是:对于 onSingleTapUp() 函数来说,只要手抬起就会被触发;而对于 onSingleTapConfirmed() 函数来说,如果双击,则该函数就不会被触发。
- onDoubleTap(MotionEvent e):双击事件。
- onDoubleTapEvent(MotionEvent e):双击间隔中发生的动作。指在触发 onDoubleTap 以后,在双击之间发生的其他动作,包含 down、up 和 move 事件。
在 13.1.2 节例子的基础上,添加双击监听,代码如下:
双击所对应的事件触发顺序如下图所示。
- 第二次单击时,先触发 onDoubleTap,再触发 onDown。
- 在触发 onDoubleTap 以后,就开始触发 onDoubleTapEvent。onDoubleTapEvent 后面的数字代表当前的事件,0 代表 ACTION_DOWN,1 代表 ACTION_UP,2 代表 ACTION_MOVE。
轻轻单击一下,对应的事件触发顺序如下:
13.1.4 GestureDetector.SimpleOnGestureListener 类
SimpleOnGestureListener 类与 OnGestureListener 和 OnDoubleTapListener 接口的不同之处在于:
1)这是一个类,在它的基础上新建类,要用 extends 派生,而不能用 implements 继承。
2)OnGestureListener 和 OnDoubleTapListener 接口里的函数都是被强制重写的,即使用不到也要重写出来一个空函数;而在 SimpleOnGestureListener 类的实例或派生类中不必如此,可以根据情况,用到哪个函数就重写哪个函数,因为 SimpleOnGestureListener 类本身已经实现了这两个接口中的所有函数,只是里面全是空的而已。
下面利用 SimpleOnGestureListener 类来重新实现前面的几个效果,代码如下:
13.1.5 onFling() 函数的应用
可以利用 onFling() 函数来识别当前用户是在左滑还是在右滑。先来看一下 onFling() 函数的参数。
参数:
- e1:第一个 ACTION_DOWN MotionEvent。
- e2:最后一个 ACTION_DOWN MotionEvent。
- velocityX:X 轴上的移动速度,单位为像素/秒。
- velocityY:Y 轴上的移动速度,单位为像素/秒。
实现的功能:当用户向左滑动距离超过 100 像素,且滑动速度超过 100 像素/秒时,即判断为向左滑动;向右同理。核心代码如下: