GestureDetector:手势识别。
文档里面这样描述:
/**
* Detects various gestures and events using the supplied {@link MotionEvent}s.
* The {@link OnGestureListener} callback will notify users when a particular
* motion event has occurred. This class should only be used with {@link MotionEvent}s
* reported via touch (don't use for trackball events).
* 使用提供的MotionEvents检测各种手势和事件。
* 一个特定的移动事件发生时,OnGestureListener回调函数会通知用户。
* 这个类只能处理由触摸引起MotionEvents(不要用于轨迹球事件)
*
* To use this class:
* <ul>
* <li>Create an instance of the {@code GestureDetector} for your {@link View}
* <li>In the {@link View#onTouchEvent(MotionEvent)} method ensure you call
* {@link #onTouchEvent(MotionEvent)}. The methods defined in your callback
* will be executed when the events occur.
* </ul>
* 如何使用这个类:
* 1、给你的View创建一个GestureDetector的实例
* 2、在你的View的onTouchEvent(MotionEvent)方法中确保调用了GestureDetector的onTouchEvent(MotionEvent)方法。
* 事件发生时,在回调方法中定义的方法会被执行
*
*/
因此可以知道GestureDetector是只能处理触摸引起的MotionEvent。也就是说我们需要把要处理的触摸事件的所有信息转交给GestureDetector来处理。
怎么使用GestureDetector呢?先来了解GestureDetector类:
在GestureDetector类的内部有两个接口OnGestureListener和OnDoubleTapListener和一个内部类SimpleOnGestureListener,
而SimpleOnGestureListener类实现了OnGestureListener, OnDoubleTapListener接口,虽然实现了两个接口,复写了所有方法,但是所有的方法都没有具体实现,是空方法。因此如果在使用GestureDetector时,如果觉得内部接口的方法太多,没有必要关心其他方法时,就可以继承内部类SimpleOnGestureListener,继承内部类SimpleOnGestureListener时,可以只重写我们关心的方法。
OnGestureListener接口,简单粗暴的翻译了下文档注释:
/**
* The listener that is used to notify when gestures occur.
* If you want to listen for all the different gestures then implement
* this interface. If you only want to listen for a subset it might
* be easier to extend {@link SimpleOnGestureListener}.
*
* 手势发生时用于通知的监听器
* 1、如果想要监听所有不同的手势,可以实现OnGestureListener监听器接口
* 2、如果只想监听部分手势,可以继承GuestureDetector的内部类SimpleOnGestureListener
*/
public interface OnGestureListener {
/**
* Notified when a tap occurs with the down {@link MotionEvent}
* that triggered it. This will be triggered immediately for
* every down event. All other events should be preceded by this.
*
* MotionEvent的down点击事件发生时执行
* 每个down事件按下时,onDown(MotionEvent e)方法都会立即触发
* onDown(MotionEvent e)方法应该优先于所有其他事件
*
* @param e The down motion event.
*/
boolean onDown(MotionEvent e);
/**
* The user has performed a down {@link MotionEvent} and not performed
* a move or up yet. This event is commonly used to provide visual
* feedback to the user to let them know that their action has been
* recognized i.e. highlight an element.
*
* 用户已经执行了MotionEvent的down事件,而且还没有移动(move)或者抬起(up)
* 此事件通常用于提供视觉反馈给用户,让用户知道,用户的动作(action)得到了认可,即突出一个元素
*
* @param e The down motion event
*/
void onShowPress(MotionEvent e);
/**
* Notified when a tap occurs with the up {@link MotionEvent}
* that triggered it.
*
* MotionEvent的up发生,即当单击发生抬起。触发onSingleTapUp(MotionEvent e)
*
* @param e The up motion event that completed the first tap
* e: 第一次点击完成
* @return true if the event is consumed, else false
* true:如果事件被消费返回true,否则返回false
*/
boolean onSingleTapUp(MotionEvent e);
/**
* Notified when a scroll occurs with the initial on down {@link MotionEvent} and the
* current move {@link MotionEvent}. The distance in x and y is also supplied for
* convenience.
*
* MotionEvent的down和MotionEvent的move初始化后,滚动(scroll)发生时执行
* 提供了在x轴和y轴方向上的距离
*
* @param e1 The first down motion event that started the scrolling.
* e1:开始滚动的第一次按下(down)事件
* @param e2 The move motion event that triggered the current onScroll.
* e2:触发当前onScroll方法的移动(move)事件
* @param distanceX The distance along the X axis that has been scrolled since the last
* call to onScroll. This is NOT the distance between {@code e1}
* and {@code e2}.
* distanceX:从最后调用onScroll方法时,已经滚动的X轴方向的距离
* 这个距离不是e1和e2之间的距离
* @param distanceY The distance along the Y axis that has been scrolled since the last
* call to onScroll. This is NOT the distance between {@code e1}
* and {@code e2}.
* distanceY:从最后调用onScroll方法时,已经滚动的Y轴方向的距离
* 这个距离不是e1和e2之间的距离
* @return true if the event is consumed, else false
* 事件被消费返回true,没有消费则返回false
*/
boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY);
/**
* Notified when a long press occurs with the initial on down {@link MotionEvent}
* that trigged it.
*
* MotionEvent的down初始化后,长按动作发生,则执行onLongPress(MotionEvent e)
*
* @param e The initial on down motion event that started the longpress.
* e: down动作事件初始化后开始的长按
*/
void onLongPress(MotionEvent e);
/**
* Notified of a fling event when it occurs with the initial on down {@link MotionEvent}
* and the matching up {@link MotionEvent}. The calculated velocity is supplied along
* the x and y axis in pixels per second.
*
* MotionEvent的down和MotionEvent的up匹配起来初始化后,一个fling事件发生
* 单位:像素每秒,px/s,沿x轴和Y轴方向的计算速度
*
* @param e1 The first down motion event that started the fling.
* e1:第一次按下(down)开始滑动(fling)的移动事件
* @param e2 The move motion event that triggered the current onFling.
* e2:当前onFling触发的move移动事件
* @param velocityX The velocity of this fling measured in pixels per second
* along the x axis.
* 单位:像素每秒,px/s,沿X轴方向的滑动测量速度
* @param velocityY The velocity of this fling measured in pixels per second
* along the y axis.
* 单位:像素每秒,px/s,沿y轴方向的滑动测量速度
* @return true if the event is consumed, else false
* 事件被消费返回true,没有消费则返回false
*/
boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY);
}
OnGestureListener接口有6个方法:
//手指按下
boolean onDown(MotionEvent e);
//手指已经按下,但是还没有移动或者抬起
void onShowPress(MotionEvent e);
//单击完成
boolean onSingleTapUp(MotionEvent e);
//手指按下并移动
boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY);
//长按
void onLongPress(MotionEvent e);
//惯性滑动,即手指按下到抬起后还在滑动
boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY);
然后看OnDoubleTapListener接口:
/**
* The listener that is used to notify when a double-tap or a confirmed
* single-tap occur.
*
* 监听器:
* 用于当双击或者已经确定的单击发生时的监听器
*/
public interface OnDoubleTapListener {
/**
* Notified when a single-tap occurs.
* 单击发生时执行
* <p>
* Unlike {@link OnGestureListener#onSingleTapUp(MotionEvent)}, this
* will only be called after the detector is confident that the user's
* first tap is not followed by a second tap leading to a double-tap
* gesture.
*
* 这个方法不同于OnGestureListener的onSingleTapUp(MotionEvent),
* 这个方法只会在识别器确定了用户的第一次点击不被第二次点击变成双击手势时被调用
* @param e The down motion event of the single-tap.
* 按下的单击事件
* @return true if the event is consumed, else false
*/
boolean onSingleTapConfirmed(MotionEvent e);
/**
* Notified when a double-tap occurs.
* 双击发生时执行
* @param e The down motion event of the first tap of the double-tap.
* 双击的第一次点击,
* @return true if the event is consumed, else false
*/
boolean onDoubleTap(MotionEvent e);
/**
* Notified when an event within a double-tap gesture occurs, including
* the down, move, and up events.
* 双击手势,包括按下(down),移动(move),抬起(up)
*
* @param e The motion event that occurred during the double-tap gesture.
* 双击手势期间发生的移动事件
* @return true if the event is consumed, else false
*/
boolean onDoubleTapEvent(MotionEvent e);
}
OnDoubleTapListener只有3个方法:
//被确定为单击,这个方法跟OnGestureListener的onSingleTapUp(MotionEvent)不同,
boolean onSingleTapConfirmed(MotionEvent e);
//双击的第一次点击
boolean onDoubleTap(MotionEvent e);
//双击事件,包括按下(down),移动(move),抬起(up)
boolean onDoubleTapEvent(MotionEvent e);
GestureDetector的内部类SimpleOnGestureListener,实现了OnGestureListener接口和OnDoubleTapListener接口的全部空方法。
/**
* A convenience class to extend when you only want to listen for a subset
* of all the gestures. This implements all methods in the
* {@link OnGestureListener} and {@link OnDoubleTapListener} but does
* nothing and return {@code false} for all applicable methods.
*
* 一个方便的类,只监听所有手势的部分手势
* 这个类实现了所有OnGestureListener接口和OnDoubleTapListener接口的所有方法,但是方法是空方法,没有具体实现,
*/
public static class SimpleOnGestureListener implements OnGestureListener, OnDoubleTapListener {
public boolean onSingleTapUp(MotionEvent e) {
return false;
}
public void onLongPress(MotionEvent e) {
}
public boolean onScroll(MotionEvent e1, MotionEvent e2,
float distanceX, float distanceY) {
return false;
}
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {
return false;
}
public void onShowPress(MotionEvent e) {
}
public boolean onDown(MotionEvent e) {
return false;
}
public boolean onDoubleTap(MotionEvent e) {
return false;
}
public boolean onDoubleTapEvent(MotionEvent e) {
return false;
}
public boolean onSingleTapConfirmed(MotionEvent e) {
return false;
}
}
接下看如何使用:
在文章开头的注释中有两个步骤:
第一步:在我们需要GestureDetector类的View中实例化一个GestureDetector。
实例化一个GestureDetector,有几个构造方法供选择,
/**
* Creates a GestureDetector with the supplied listener.
* This variant of the constructor should be used from a non-UI thread
* (as it allows specifying the Handler).
*
* 创建一个支持监听器(listener)的GestureDetector
* 创建的实例应在在非UI线程中使用(因为它允许指定Handler)
*
* @param listener the listener invoked for all the callbacks, this must
* not be null.
* 给所有回调函数调用的监听器,此参数不能为空
* @param handler the handler to use
* 使用的处理者
*
* @throws NullPointerException if either {@code listener} or
* {@code handler} is null.
*
* @deprecated Use {@link #GestureDetector(android.content.Context,
* android.view.GestureDetector.OnGestureListener, android.os.Handler)} instead.
* 此构造函数已经被废弃,取而代之的是带有上下文参数的GestureDetector(android.content.Context,
* android.view.GestureDetector.OnGestureListener, android.os.Handler)
*/
@Deprecated
public GestureDetector(OnGestureListener listener, Handler handler) {
this(null, listener, handler);
}
/**
* Creates a GestureDetector with the supplied listener.
* You may only use this constructor from a UI thread (this is the usual situation).
* @see android.os.Handler#Handler()
*
* 创建一个支持监听器(listener)的GestureDetector
* 只能从UI线程使用此构造(这是一般情况)
*
* @param listener the listener invoked for all the callbacks, this must
* not be null.
* 给所有回调函数调用的监听器,此参数不能为空
* @throws NullPointerException if {@code listener} is null.
*
* @deprecated Use {@link #GestureDetector(android.content.Context,
* android.view.GestureDetector.OnGestureListener)} instead.
*
* 此构造函数已经被废弃,取而代之的是带有上下文参数的GestureDetector(android.content.Context,
* android.view.GestureDetector.OnGestureListener)
*/
@Deprecated
public GestureDetector(OnGestureListener listener) {
this(null, listener, null);
}
/**
* Creates a GestureDetector with the supplied listener.
* You may only use this constructor from a {@link android.os.Looper} thread.
* @see android.os.Handler#Handler()
*
* 创建一个支持监听器(listener)的GestureDetector
* 只能从线程(thread)中使用这个构造函数
*
* @param context the application's context
* 应用程序的上下文
* @param listener the listener invoked for all the callbacks, this must
* not be null.
* 给所有回调函数调用的监听器,此参数不能为空
*
* @throws NullPointerException if {@code listener} is null.
*/
public GestureDetector(Context context, OnGestureListener listener) {
this(context, listener, null);
}
/**
* Creates a GestureDetector with the supplied listener that runs deferred events on the
* thread associated with the supplied {@link android.os.Handler}.
* @see android.os.Handler#Handler()
*
* 创建一个带有监听器的GestureDetector,运行延迟监听事件在线程中,这个线程和Handler相关
*
* @param context the application's context
* 应用程序的上下文
* @param listener the listener invoked for all the callbacks, this must
* not be null.
* 给所有回调函数调用的监听器,此参数不能为空
* @param handler the handler to use for running deferred listener events.
* 该处理者(Handler)用于运行延迟监听事件。
*
* @throws NullPointerException if {@code listener} is null.
*/
public GestureDetector(Context context, OnGestureListener listener, Handler handler) {
if (handler != null) {
mHandler = new GestureHandler(handler);
} else {
mHandler = new GestureHandler();
}
mListener = listener;
if (listener instanceof OnDoubleTapListener) {
setOnDoubleTapListener((OnDoubleTapListener) listener);
}
init(context);
}
/**
* Creates a GestureDetector with the supplied listener that runs deferred events on the
* thread associated with the supplied {@link android.os.Handler}.
* @see android.os.Handler#Handler()
*
* 创建一个带有监听器的GestureDetector,运行延迟监听事件在线程中,这个线程和Handler相关
* @param context the application's context
* 应用程序的上下文
* @param listener the listener invoked for all the callbacks, this must
* not be null.
* 给所有回调函数调用的监听器,此参数不能为空
* @param handler the handler to use for running deferred listener events.
* 该处理者(Handler)用于运行延迟监听事件。
* @param unused currently not used.
* 现在还没有被使用
*
* @throws NullPointerException if {@code listener} is null.
*/
public GestureDetector(Context context, OnGestureListener listener, Handler handler,
boolean unused) {
this(context, listener, handler);
}
可以发现,其中有两个构造方法过期了:
@Deprecated
public GestureDetector(OnGestureListener listener, Handler handler) {
this(null, listener, handler);
}
@Deprecated
public GestureDetector(OnGestureListener listener) {
this(null, listener, null);
}
public GestureDetector(Context context, OnGestureListener listener, Handler handler) {
if (handler != null) {
mHandler = new GestureHandler(handler);
} else {
mHandler = new GestureHandler();
}
mListener = listener;
if (listener instanceof OnDoubleTapListener) {
setOnDoubleTapListener((OnDoubleTapListener) listener);
}
init(context);
}
第二个则被下面这个代替:
public GestureDetector(Context context, OnGestureListener listener) {
this(context, listener, null);
}
但是还是可以使用,下面这个还没开始使用:
public GestureDetector(Context context, OnGestureListener listener, Handler handler,
boolean unused) {
this(context, listener, handler);
}
第二步:把我们的View的onTouchEvent交给GestureDetector的onTouchEvent处理
@Override
public boolean onTouchEvent(MotionEvent event) {
return mGestureDetector.onTouchEvent(event);
}
第三步:然后就在GestureDetector的监听器中重写监听触摸事件的方法
小实例:这里重写了所有方法,只是打印信息。
package com.zwc.admin.scrollerdemo;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;
public class GestureDetectorTestActivity extends ActionBarActivity {
private static final String TAG = "GestureDetectorTestActivity";
private GestureDetector mGestureDetector;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_gesture_detector_test);
//初始化监听器
if (null == mGestureDetector) {
mGestureDetector = new GestureDetector(GestureDetectorTestActivity.this,
new MySimpleOnGestureListener());
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
return mGestureDetector.onTouchEvent(event);
}
private static class MySimpleOnGestureListener extends GestureDetector.SimpleOnGestureListener {
public MySimpleOnGestureListener() {
super();
}
@Override
public boolean onSingleTapUp(MotionEvent e) {
Log.e(TAG, "onSingleTapUp(MotionEvent e)");
return super.onSingleTapUp(e);
}
@Override
public void onLongPress(MotionEvent e) {
Log.e(TAG, "onLongPress(MotionEvent e)");
super.onLongPress(e);
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
Log.e(TAG, "onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY)");
return super.onScroll(e1, e2, distanceX, distanceY);
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
Log.e(TAG, "onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY)");
return super.onFling(e1, e2, velocityX, velocityY);
}
@Override
public void onShowPress(MotionEvent e) {
Log.e(TAG, "onShowPress(MotionEvent e)");
super.onShowPress(e);
}
@Override
public boolean onDown(MotionEvent e) {
Log.e(TAG, "onDown(MotionEvent e)");
return super.onDown(e);
}
@Override
public boolean onDoubleTap(MotionEvent e) {
Log.e(TAG, "onDoubleTap(MotionEvent e)");
return super.onDoubleTap(e);
}
@Override
public boolean onDoubleTapEvent(MotionEvent e) {
Log.e(TAG, "onDoubleTapEvent(MotionEvent e)");
return super.onDoubleTapEvent(e);
}
@Override
public boolean onSingleTapConfirmed(MotionEvent e) {
Log.e(TAG, "onSingleTapConfirmed(MotionEvent e)");
return super.onSingleTapConfirmed(e);
}
}
}