今天来详细说一下android中常常使用的GestureDetector。先来看看google对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). * * 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> */
上面主要说了GestureDetector的作用和使用方法,这里我先做一下大意的翻译:GestureDetector可以通过view的onTouchEvent带回的MotionEvent来判断出特殊的手势,当检测到有特殊的手势发生时,就会回调对应的特殊方法来告知用户。

从上述可以知道,对于GestureDetector的使用主要有两个地方需要我们自己来做:

(1)在需要检测手势的view或者activity等 ,需要在其onTouchEvent(MotionEvent event)方法里面实时将event信息传递给你的GestureDetector对象,比如下来这样:

    @Override    public boolean onTouchEvent(MotionEvent event) {        // TODO Auto-generated method stub        return this.detector.onTouchEvent(event);    }
(2)上面说,当有特殊的手势时候会调用特殊的回调方法,所以这里还需要我们去写对于特殊手势的回调函数。GestureDetector里面定义了不同的接口函数来对应不同的手势。所以我们只需要实现GestureDetector里面的手势接口方法即可。

GestureDetector的手势接口分两种:OnGestureListener主要处理单点触摸、OnDoubleTapListener主要是处理两点触摸。一般情况,你希望用到那一种就实现一种的接口就可以了。然后把实现手势接口的对象传递给你的GestureDetector就可以了。

在GestureDetector.java有其对GestureDetector的定义,从中可以看到定义的一个变量 private final OnGestureListener mListener; 其中mListener就是指向我们自己实现手势接口的对象。我们来看看GestureDetector的一个最终的构造函数:

    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);    }


下面我们来一个实例(一个手电筒APP中用到的GestureDetector):

public class LightActivity extends Activity implements OnTouchListener, OnGestureListener {    private static String MY_PKG_NAME = "com.android.camera";    private LinearLayout mlayout;    private GestureDetector detector; // 申明一个<span style="font-family:Arial, Helvetica, sans-serif;">GestureDetector </span>......    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        this.requestWindowFeature(Window.FEATURE_NO_TITLE);        setContentView(R.layout.activity_light);        CloseCamera();        mlayout = (LinearLayout) findViewById(R.id.mlayou);        detector = new GestureDetector(this); // 实例化一个对象,这里传递的是<span style="font-family:Arial, Helvetica, sans-serif;">LightActivity对象,因为</span><span style="font-family:Arial, Helvetica, sans-serif;">LightActivity实现了</span><span style="font-family:Arial, Helvetica, sans-serif;">OnGestureListener 接口</span><span style="font-family:Arial, Helvetica, sans-serif;"></span><span style="font-family:Arial, Helvetica, sans-serif;"></span>        Resources resources = this.getResources();......}......    @Override    public boolean onTouchEvent(MotionEvent event) {        // TODO Auto-generated method stub        return this.detector.onTouchEvent(event); //  这里实时将<span style="font-family:Arial, Helvetica, sans-serif;">MotionEvent 传递给我们的</span><span style="font-family:Arial, Helvetica, sans-serif;">detector</span><span style="font-family:Arial, Helvetica, sans-serif;"></span>    }......
// 下面你的几个方法是实现接口<span style="font-family:Arial, Helvetica, sans-serif;">OnGestureListener</span>    @Override    public boolean onDown(MotionEvent e) {        // TODO Auto-generated method stub        return false;    }    @Override    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {        // TODO Auto-generated method stub        // ￯﾿ᄑ￯﾿ᄑ￯﾿ᄑ￯﾿ᄑ        /*         * if (e1.getX() - e2.getX() > FLING_MIN_DISTANCE && Math.abs(velocityX)         * > FLING_MIN_VELOCITY) { if (IsOpenFlash) { // Fling left         * mVibrator.vibrate(off, -1); closeFlashLight();         * mlayout.setBackgroundDrawable(mdrawable_off); } } else if (e2.getX()         * - e1.getX() > FLING_MIN_DISTANCE && Math.abs(velocityX) >         * FLING_MIN_VELOCITY) { if (!IsOpenFlash) { // Fling right         * mVibrator.vibrate(on, -1); openFlashLight();         * mlayout.setBackgroundDrawable(mdrawable_on); } }         */        return false;    }    @Override    public void onLongPress(MotionEvent e) {        // TODO Auto-generated method stub    }    @Override    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {        // TODO Auto-generated method stub        // 锟斤拷锟斤拷        if ((e1.getY() > MAX_UP && e2.getY() < MAX_DOWN)                && (e1.getX() > MAX_LEFT && e2.getX() < MAX_RIGHT)) {            if (e1.getY() - e2.getY() > FLING_MIN_DISTANCE                    && Math.abs(distanceY) > FLING_MIN_VELOCITY) {                if (!IsOpenFlash) {                    // Fling up                    mVibrator.vibrate(on, -1);                    openFlashLight();                    mlayout.setBackgroundDrawable(mdrawable_on);                }            } else if (e2.getY() - e1.getY() > FLING_MIN_DISTANCE                    && Math.abs(distanceY) > FLING_MIN_VELOCITY) {                if (IsOpenFlash) {                    // Fling down                    mVibrator.vibrate(off, -1);                    closeFlashLight();                    mlayout.setBackgroundDrawable(mdrawable_off);                }            }        }        return false;    }    @Override    public void onShowPress(MotionEvent e) {        // TODO Auto-generated method stub    }    @Override    public boolean onSingleTapUp(MotionEvent e) {        // TODO Auto-generated method stub        return false;    }......}
最后我们来介绍一下GestureDetector的手势接口方法:

(1)OnGestureListener

boolean onDown(MotionEvent e); // 点击时候一触摸到屏就会发生

void onShowPress(MotionEvent e); // 在点击触摸到屏时候、并且move or up都还没有发生时候 就会发生。其实就是在onDown之后,原则上第一个会发生的手势。

boolean onSingleTapUp(MotionEvent e); // 当单个点击触摸屏UP(离开)的时候发生的手势,这里为什么是SingleTap呢? 就是要区别多点触摸,所以这里其实是指只有一个手指触摸屏时候,up(离开屏)的时候发生的手势。

void onLongPress(MotionEvent e);// 长按手势

boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY);// 是指触摸屏的时候,在屏上面滑动的时候发生的手势,其实上是在MotionEvent.ACTION_MOVE的时候才会发生的手势。

boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY); // 这个和onScroll不一样,这个主要是用于识别用户在move的时候,突然UP的时候才会发生的手势。velocityX 和velocityY是指速率(这里是一个second移动的距离);MotionEvent e1当前这个手势发生的down motion event ;MotionEvent e2 发生这个手势的move motion event。onFling主要用于判断用户的意图,

对于onFling和onScroll我们来举例说明:onScroll一般用于识别用户对图片的放大、缩小意图;onFling常用于识别用户看电子 书的时候翻页的意图。

(2)OnDoubleTapListener:

boolean onSingleTapConfirmed(MotionEvent e); // 确认只是一次点击的时候发生的手势,这里其实是第一次点击后,一段时间内没有再收到一个一个点击,则发生该手势。这里的一段时间其实就是一点确认是否是双击的时间:ViewConfiguration.getDoubleTapTimeout()。在ViewConfiguration.java里面有其定义时间长度:

    /**     * Defines the duration in milliseconds between the first tap's up event and     * the second tap's down event for an interaction to be considered a     * double-tap.     */    private static final int DOUBLE_TAP_TIMEOUT = 300;

boolean onDoubleTap(MotionEvent e);// 双击的时候发生的手势。参数:MotionEvent e 是指第一次点击的事件。

boolean onDoubleTapEvent(MotionEvent e);//// 双击发生的过程中发生的手势。


其实GestureDetector的处理核心代码是public boolean onTouchEvent(MotionEvent ev),这个方法做了所有对手势的检测和区分。如还是不太理解各个手势是如何发生的话可以去看看这个方法。



更多相关文章

  1. [置顶] 调用Android发短信接口Intent.ACTION_SENDTO
  2. Android中的Parcelable接口
  3. Android 接口定义语言 (AIDL)
  4. Android中回调接口的使用
  5. Android手势滑动Tab
  6. Android网络应用接口
  7. android图片缩放手势检测类--ScaleGestureDetector
  8. Android手势下拉抽屉效果
  9. Android 滑动手势侦测方法介绍

随机推荐

  1. 【Android】调用系统应用常用uri & inten
  2. Androd学习笔记——Android中Touch事件的
  3. 【转】How to port native (C/C++) libra
  4. 《Android 获取当前app的版本号和版本名
  5. Android(安卓)Studio运行Hello World程序
  6. android 中给图片加圆角效果
  7. Android API 中文 (112) ―― ThumbnailU
  8. Android Binder机制(三) ServiceManager
  9. Android屏幕截图实现 (adbd部分)
  10. Ubuntu10.04 LTS 下编译Android