触摸事件与手势监听GestureDetector详解

目录

  • 事件监听的方法
  • GestureDetector类
  • GestureDetector使用方法
  • GesturetDetector.OnGestureListener 接口
  • GesttureDetector.OnDoubleTapListener 接口
  • GesttureDetector.SimpleOnGestureListener 类

1:事件监听的方法

在android应用层上主要有两个层面的触摸事件监听,一个是Activity层,另一个是View层。方法主要有三种: 
第一是Activity中重写父类中的public boolean onTouchEvent(MotionEvent event)方法;

@Override
    public boolean onTouchEvent(MotionEvent event) {
        return super.onTouchEvent(event);
    }
  • 1
  • 2
  • 3
  • 4

第二个是重写View类中的GestDetector.OnGestureListener 接口中定义的boolean onTouch(View v, MotionEvent event);

@Override
    public boolean onTouch(View v, MotionEvent event) {
        return false;
    }
  • 1
  • 2
  • 3
  • 4

第三个是利用GestureDetector.onTouchEvent(event)在View.onTouch方法中来接管事件处理

@Override
    public boolean onTouch(View v, MotionEvent event) {
        return mGestureDetector.onTouchEvent(event);
    }
  • 1
  • 2
  • 3
  • 4

当view上的事件被分发到view上时触发onTouch方法的回调, 如果这个方法返回false时,表示事件处理失败,该事件就会被传递给相应的Activity中的onTouchEvent方法来处理。 
如果该方法返回true时,表示该事件已经被onTouch函数处理完,不会上传到activity中处理。


2:GestureDector类

GestureDector类需要注意以下内容:

  • OnGestureListener接口
  • OnDoubleTapListener双击接口
  • SimpleOnGestureListener 类(实现了类内的三个接口)
  • onTouchEvent()方法
  • setOnDoubleTapListener()双击监听

当屏幕上发生特定的触摸事件,就会去回调GestureDector.OnGestureListener和GestureDetector.OnDoubleTapListener接口中相应的回调函数来监测各样的手势和事件,并且通知用户。但是这些触发函数都没有具体的实现,我们必须实现这些接口,并重写这些方法的具体实现。 
GestureDetector类中已经为我们定义了一个静态内部类SimpleOnGestureListener,它实现了OnGestureListener,OnDoubleTapListener,OnContextClickListener接口,定义为

 public static class SimpleOnGestureListener implements OnGestureListener, OnDoubleTapListener,
            OnContextClickListener 
  • 1
  • 2

SimpleOnGestureListener类内重写接口中的所有方法,但是都是空实现,返回的布尔值都是false。主要作用是方便我们继承这个类有选择的复写回调方法,而不是实现接口去重写所有的方法。 
onTouchEvent()方法用来分析传入的事件,如果匹配的话就去触发OnGestureListener中相应的回调方法。 
如果要监听双击事件必须调用GestureDector.setOnDoubleTapListener()


3:GestureDetector使用方法

第一步:实现OnGestureListener接口中的方法(可以使用匿名内部类或实现了接口的类实例) 
内部类形式

class MyGestureListener implements GestureDetector.OnGestureListener {

        @Override
        public boolean onDown(MotionEvent e) {
            return false;
        }

        @Override
        public void onShowPress(MotionEvent e) {

        }

        @Override
        public boolean onSingleTapUp(MotionEvent e) {
            return false;
        }

        @Override
        public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
            return false;
        }

        @Override
        public void onLongPress(MotionEvent e) {

        }

        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
            return false;
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

匿名内部类形式

mGestureDetector = new GestureDetector(mContext, new GestureDetector.OnGestureListener() {
            @Override
            public boolean onDown(MotionEvent e) {
                return false;
            }

            @Override
            public void onShowPress(MotionEvent e) {

            }

            @Override
            public boolean onSingleTapUp(MotionEvent e) {
                return false;
            }

            @Override
            public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
                return false;
            }

            @Override
            public void onLongPress(MotionEvent e) {

            }

            @Override
            public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
                return false;
            }
        });
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

第二步:创建GestureDetector类的实例,构造函数如下:

public GestureDetector(OnGestureListener listener, Handler handler) {
        this(null, listener, handler);
    }
  • 1
  • 2
  • 3
public GestureDetector(OnGestureListener listener) {
        this(null, listener, null);
    }
  • 1
  • 2
  • 3
public GestureDetector(Context context, OnGestureListener listener) {
        this(context, listener, null);
    }
  • 1
  • 2
  • 3
public GestureDetector(Context context, OnGestureListener listener, Handler handler)
  • 1
public GestureDetector(Context context, OnGestureListener listener, Handler handler,
            boolean unused) {
        this(context, listener, handler);
    }
  • 1
  • 2
  • 3
  • 4

前两个已经废弃了。

mGestureDetector = new GestureDetector(mContext,new MyGestureListener());
  • 1

第三步:实现View.OnTouchListener接口,重写onTouch()方法 
第四步:在onTouch()方法中拦截事件处理,将控制权交给GestureDector。

@Override
    public boolean onTouch(View v, MotionEvent event) {
        return mGestureDetector.onTouchEvent(event);
    }
  • 1
  • 2
  • 3
  • 4

第五步:调用控件的View.setOnTouchListener()将接口的具体实现的引用传递进去或者如果是监听双击的话调用GestureDetector .setOnDoubleTapListener()

super.setOnTouchListener(this);
  • 1
mGestureDetector.setOnDoubleTapListener(new MyGestureListener());
  • 1

完整代码

package com.example.gesturetest;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;

/**
 * Created by pingkun.huang on 2016/4/16.
 */
public class MyView extends View implements View.OnTouchListener{
    private Context mContext;
    private GestureDetector mGestureDetector;
    private static final String TAG = "MyView";
    public MyView(Context context) {
        super(context);
        initData(context);
    }

    public MyView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initData(context);
    }

    public MyView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initData(context);
    }


    private void initData(Context context) {
        this.mContext = context;
        super.setOnTouchListener(this);
        super.setClickable(true);
        super.setLongClickable(true);
        super.setFocusable(true);
        mGestureDetector = new GestureDetector(mContext,new MyGestureListener());
        mGestureDetector.setOnDoubleTapListener(new MyGestureListener());
    }

    /*
    * 当该view上的事件被分发到view上时触发该方法的回调
    * 如果这个方法返回false时,该事件就会被传递给Activity中的onTouchEvent方法来处理
    * 如果该方法返回true时,表示该事件已经被onTouch函数处理玩,不会上传到activity中处理
    * 该方法属于View.OnTouchListening接口
    * */
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        return mGestureDetector.onTouchEvent(event);
    }


    /*
    *
    * 手势监听类
    * */
    class MyGestureListener extends GestureDetector.SimpleOnGestureListener {
        public MyGestureListener() {
            super();
        }
        @Override
        public boolean onDoubleTap(MotionEvent e) {
            Log.e(TAG, "onDoubleTap");
            return true;
        }

        @Override
        public boolean onDoubleTapEvent(MotionEvent e) {
            Log.e(TAG, "onDoubleTapEvent");
            return true;
        }

        @Override
        public boolean onSingleTapConfirmed(MotionEvent e) {
            Log.e(TAG, "onSingleTapConfirmed");
            return true;
        }

        @Override
        public boolean onContextClick(MotionEvent e) {
            Log.e(TAG, "onContextClick");
            return true;
        }

        @Override
        public boolean onDown(MotionEvent e) {
            Log.e(TAG, "onDown");
            return true;
        }

        @Override
        public void onShowPress(MotionEvent e) {
            Log.e(TAG, "onShowPress");
        }

        @Override
        public boolean onSingleTapUp(MotionEvent e) {
            Log.e(TAG, "onSingleTapUp");
            return true;
        }

        @Override
        public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
            Log.e(TAG, "onScroll");
            return true;
        }

        @Override
        public void onLongPress(MotionEvent e) {
            Log.e(TAG, "onLongPress");
        }

        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
            Log.e(TAG, "onFling");
            return true;
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122

MyView是一个自定义控件继承了View实现了View.OnTouchListener。监听的方法用的是继承SimpleOnGestureListener类,重写了所有方法,仅打印log日志,具体功能自己根据业务重写。


4:GesturetDetector.OnGestureListener 接口

class MyGestureListener implements GestureDetector.OnGestureListener {

        @Override
        /*
        *每按一下屏幕立即触发
        * */
        public boolean onDown(MotionEvent e) {
            return false;
        }

        @Override
        /*
        *用户按下屏幕并且没有移动或松开。主要是提供给用户一个可视化的反馈,告诉用户他们的按下操作已经
        * 被捕捉到了。如果按下的速度很快只会调用onDown(),按下的速度稍慢一点会先调用onDown()再调用onShowPress().
        * */
        public void onShowPress(MotionEvent e) {

        }

        @Override
        /*
        *一次单纯的轻击抬手动作时触发
        * */
        public boolean onSingleTapUp(MotionEvent e) {
            return false;
        }

        @Override
        /*
        *屏幕拖动事件,如果按下的时间过长,调用了onLongPress,再拖动屏幕不会触发onScroll。拖动屏幕会多次触发
        * @param e1 开始拖动的第一次按下down操作,也就是第一个ACTION_DOWN
        * @parem e2 触发当前onScroll方法的ACTION_MOVE
        * @param distanceX 当前的x坐标与最后一次触发scroll方法的x坐标的差值。
        * @param diastancY 当前的y坐标与最后一次触发scroll方法的y坐标的差值。
        * */
        public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
            return false;
        }

        @Override
        /*
        * 长按。在down操作之后,过一个特定的时间触发
        * */
        public void onLongPress(MotionEvent e) {

        }

        @Override
        /*
        * 按下屏幕,在屏幕上快速滑动后松开,由一个down,多个move,一个up触发
        * @param e1 开始快速滑动的第一次按下down操作,也就是第一个ACTION_DOWN
        * @parem e2 触发当前onFling方法的move操作,也就是最后一个ACTION_MOVE
        * @param velocityX:X轴上的移动速度,像素/秒
        * @parram velocityY:Y轴上的移动速度,像素/秒
        * */
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
            return false;
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59

快按屏幕:onDown 
慢按屏幕:onDown–>onShowPress 
按下屏幕等待一段时间onDown–>onShowPress–>onLongPress 
拖动屏幕:onDown–>onShowPress–>onScroll(多个)–>onFling 
快速滑动:onDown–>onScroll(多个)–>onFling


5:GesttureDetector.OnDoubleTapListener 接口

 class MyDoubleTapListener implements GestureDetector.OnDoubleTapListener {
        @Override
        /*
        * 单击事件。用来判定该次点击是单纯的SingleTap而不是DoubleTap,如果连续点击两次就是DoubleTap手势,
        * 如果只点击一次,系统等待一段时间后没有收到第二次点击则判定该次点击为SingleTap而不是DoubleTap,
        * 然后触发SingleTapConfirmed事件。触发顺序是:OnDown->OnsingleTapUp->OnsingleTapConfirmed
        * 关于onSingleTapConfirmed和onSingleTapUp的一点区别:二者的区别是:onSingleTapUp,只要手抬起就会执行,
        * 而对于onSingleTapConfirmed来说,如果双击的话,则onSingleTapConfirmed不会执行。
        * */
        public boolean onSingleTapConfirmed(MotionEvent e) {
            return false;
        }

        @Override
        /*
        *
        * 双击事件
        * */
        public boolean onDoubleTap(MotionEvent e) {
            return false;
        }

        @Override
        /*
        *
        *双击间隔中发生的动作。指触发onDoubleTap以后,在双击之间发生的其它动作,包含down、up和move事件
        * */
        public boolean onDoubleTapEvent(MotionEvent e) {
            return false;
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

双击:onDown–>onSingleTapUp–>onDoubleTap–>onDoubleTapEvent–>onDown–>onDoubleTapEvent

猜你喜欢

转载自blog.csdn.net/liudongdong19/article/details/80512204