Android中的手势识别,无非是系统对触屏信息的一个包装处理结果。如果要实现手势识别功能,首先需要实现OnTouchListener接口,并设置setOnTouchListener,最后在重载的函数onTouch()中,将MotionEvent交给GestureDetector去处理,典型的方式是gestureDetector.onTouchEvent(motionEvent)。
概括一下手势操作的原理
首先,在Android系统中,每一次手势交互都会依照以下顺序执行。
1. 接触接触屏一刹那,触发一个MotionEvent事件。
2. 该事件被OnTouchListener监听,在其onTouch()方法里获得该MotionEvent对象。
3. 通过GestureDetector转发MotionEvent对象至OnGestureListener。
4. OnGestureListener获得该对象,根据该对象封装的的信息,响应对应的接口函数。
而GestureDetector提供了两个侦听器接口,OnGestureListener处理单击类消息,而OnDoubleTapListener处理双击类消息。
OnGestureListener的接口有这几个:
abstract boolean onDown(MotionEvent e); //单击,触摸屏按下时立刻触发
abstract boolean onSingleTapUp(MotionEvent e); //抬起,手指离开触摸屏时触发(长按、滚动、滑动时,不会触发这个手势)
abstract void onShowPress(MotionEvent e); //短按,触摸屏按下后片刻后抬起,会触发这个手势,如果迅速抬起则不会
abstract void onLongPress(MotionEvent e); //长按,触摸屏按下后既不抬起也不移动,保持着按下,过一段时间后触发
abstract boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY); //滚动,触摸屏按下后移动,抬起时触发
abstract boolean onFling(MotionEvente1, MotionEvent e2, float velocityX, float velocityY); //滑动,触摸屏按下后快速移动并抬起,会先触发滚动手势,跟着触发一个滑动手势
OnDoubleTapListener的接口有这几个:
abstract boolean onDoubleTap(MotionEvent e); //双击,手指在触摸屏上迅速点击两次,第二下的按下触发
abstract boolean onDoubleTapEvent(MotionEvent e); //双击,第二下的按下和抬起各触发一次
abstract boolean onSingleTapConfirmed(MotionEvent e); //单击确认,即很快的按下并抬起,但并不连续点击第二下
有时候我们并不需要处理上面所有手势,而方便起见,Android提供了另外一个类SimpleOnGestureListener实现了如上接口,我们只需要继承SimpleOnGestureListener然后重载感兴趣的手势即可,这个可以通过内部类来实现。
在这里需要特别说明一点,如果你想程序能够正确识别单击和双击,那你需要重写的函数是onSingleTapConfirmed和onDoubleTap,而不是onSingleTapUp和onDoubleTap。因为在响应onDoubleTap之前,是一定会响应onSingleTapUp的,这样会造成单双击混淆的结果。还需要提醒的是,程序响应onSingleTapConfirmed会有一定的延时,因为程序需要确认是单击而不是双击,这在一定程序上会影响用户体验,需要权衡。
另外,onDown只要按下一定是立刻触发;而按下后过一会没有滑动先触发onShowPress再是onLongPress;如果按下后一直不滑动,触发顺序是onDown->onShowPress->onLongPress。如果点击一下非常快的(不滑动)然后抬起:onDown->onSingleTapUp->onSingleTapConfirmed。
点击一下稍微慢点的(不滑动)然后抬起:onDown->onShowPress->onSingleTapUp->onSingleTapConfirmed。
进一步总结的还有:
任何手势动作都会先执行一次按下(onDown)动作。
长按(onLongPress)动作前一定会执行一次按住(onShowPress)动作。
按住(onShowPress)动作和按下(onDown)动作之后都会执行一次抬起(onSingleTapUp)动作。
长按(onLongPress)、滚动(onScroll)和滑动(onFling)动作之后都不会执行抬起(onSingleTapUp)动作。