Android 手势相关(一)

Android 手势相关(一)

本篇文章主要记录下android 手势相关的一些内容.

Android 提供了一套强大的手势识别框架,可以用来检测和处理用户的手势操作.

1: 手势识别

Android 提供了GestureDetector类来识别手势,通过GestureDetector可以检测用户的滑动,长按,双击等手势操作.

2: 手势监听器

android 中处理手势操作,需要我们实现GestureDetector.OnGestureListener接口,或者继承GestureDetector.SimpleOnGestureListener.

这里我们分开来讲述下这两种方式.

3: OnGestureListener接口

我们先实现下接口,添加打印日志:

java 复制代码
public class MyGesture implements GestureDetector.OnGestureListener {
    private static final String TAG = "MyGesture";

    @Override
    public boolean onDown(MotionEvent e) {
        Log.i(TAG, "onDown: "+e);
        return false;
    }

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

    @Override
    public boolean onSingleTapUp(MotionEvent e) {
        Log.i(TAG, "onSingleTapUp: "+e);
        return false;
    }

    @Override
    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
        Log.i(TAG, "onScroll: " +e1+" "+e2);
        return false;
    }

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

    @Override
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
        Log.i(TAG, "onFling: "+e1 +" "+e2);
        return false;
    }
}
  1. onDown(): 手势按下 MotionEvent.ACTION_DOWN
  2. onShowPress(): 用户已经按下,但是还没有执行移动/向上的移动操作.(这里我们可以给出高亮显示,增强显示效果) MotionEvent.ACTION_DOWN
  3. onSingleTapUp(): 用户手势抬起时的动作. MotionEvent.ACTION_UP
  4. onScroll(): 屏幕滑动 包括两个MotionEvent.ACTION_DOWN,MotionEvent.ACTION_MOVE
  5. onLongPress(): 长按 ACTION_DOWN
  6. onFling():迅速滑动

测试:

1: 手势按下->抬起

onDown->onSingleTapUp

java 复制代码
2024-03-27 11:22:18.236 6675-6675/? I/MyGesture: onDown: 
    MotionEvent { action=ACTION_DOWN, actionButton=0, id[0]=0, x[0]=359.5007, y[0]=444.70743, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=175867619, downTime=175867619, deviceId=2, source=0x1002, displayId=0 }

2024-03-27 11:22:18.294 6675-6675/? I/MyGesture: onSingleTapUp: 
    MotionEvent { action=ACTION_UP, actionButton=0, id[0]=0, x[0]=359.5007, y[0]=444.70743, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=175867683, downTime=175867619, deviceId=2, source=0x1002, displayId=0 }
2: 长按不抬起

onDown->onShowPress->onLongPress

java 复制代码
2024-03-27 11:24:31.611 6675-6675/? I/MyGesture: onDown: 
    MotionEvent { action=ACTION_DOWN, actionButton=0, id[0]=0, x[0]=550.2358, y[0]=541.6437, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=176000997, downTime=176000997, deviceId=2, source=0x1002, displayId=0 }

2024-03-27 11:24:31.706 6675-6675/? I/MyGesture: onShowPress: 
    MotionEvent { action=ACTION_DOWN, actionButton=0, id[0]=0, x[0]=550.2358, y[0]=541.6437, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=176000997, downTime=176000997, deviceId=2, source=0x1002, displayId=0 }

2024-03-27 11:24:32.008 6675-6675/? I/MyGesture: onLongPress: 
    MotionEvent { action=ACTION_DOWN, actionButton=0, id[0]=0, x[0]=550.2358, y[0]=541.6437, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=176000997, downTime=176000997, deviceId=2, source=0x1002, displayId=0 }
3: 屏幕上来回滑动

onDown->onShowPress->onScroll->onScroll

java 复制代码
2024-03-27 11:26:18.190 6675-6675/? I/MyGesture: onDown: 
    MotionEvent { action=ACTION_DOWN, actionButton=0, id[0]=0, x[0]=146.79613, y[0]=707.53455, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=176107576, downTime=176107576, deviceId=2, source=0x1002, displayId=0 }

2024-03-27 11:26:18.285 6675-6675/? I/MyGesture: onShowPress: 
    MotionEvent { action=ACTION_DOWN, actionButton=0, id[0]=0, x[0]=146.79613, y[0]=707.53455, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=176107576, downTime=176107576, deviceId=2, source=0x1002, displayId=0 }

2024-03-27 11:26:18.345 6675-6675/? I/MyGesture: onScroll: 
    MotionEvent { action=ACTION_DOWN, actionButton=0, id[0]=0, x[0]=146.79613, y[0]=707.53455, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=176107576, downTime=176107576, deviceId=2, source=0x1002, displayId=0 } 
    MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=195.22885, y[0]=706.0355, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=2, eventTime=176107730, downTime=176107576, deviceId=2, source=0x1002, displayId=0 }


2024-03-27 11:26:18.361 6675-6675/? I/MyGesture: onScroll: 
    MotionEvent { action=ACTION_DOWN, actionButton=0, id[0]=0, x[0]=146.79613, y[0]=707.53455, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=176107576, downTime=176107576, deviceId=2, source=0x1002, displayId=0 } 
    MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=245.15952, y[0]=705.03613, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=2, eventTime=176107747, downTime=176107576, deviceId=2, source=0x1002, displayId=0 }
4: 快速划过

onDown->onScroll->onScroll->onFling

java 复制代码
2024-03-27 11:28:58.135 6675-6675/? I/MyGesture: onDown: 
    MotionEvent { action=ACTION_DOWN, actionButton=0, id[0]=0, x[0]=185.74203, y[0]=596.6075, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=176267521, downTime=176267521, deviceId=2, source=0x1002, displayId=0 }
2024-03-27 11:28:58.170 6675-6675/? I/MyGesture: onScroll: 
    MotionEvent { action=ACTION_DOWN, actionButton=0, id[0]=0, x[0]=185.74203, y[0]=596.6075, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=176267521, downTime=176267521, deviceId=2, source=0x1002, displayId=0 } 
    MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=361.2865, y[0]=554.5809, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=3, eventTime=176267556, downTime=176267521, deviceId=2, source=0x1002, displayId=0 }
2024-03-27 11:28:58.187 6675-6675/? I/MyGesture: onScroll: 
    MotionEvent { action=ACTION_DOWN, actionButton=0, id[0]=0, x[0]=185.74203, y[0]=596.6075, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=176267521, downTime=176267521, deviceId=2, source=0x1002, displayId=0 } 
    MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=519.8522, y[0]=535.2958, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=2, eventTime=176267573, downTime=176267521, deviceId=2, source=0x1002, displayId=0 }
2024-03-27 11:28:58.204 6675-6675/? I/MyGesture: onScroll: 
    MotionEvent { action=ACTION_DOWN, actionButton=0, id[0]=0, x[0]=185.74203, y[0]=596.6075, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=176267521, downTime=176267521, deviceId=2, source=0x1002, displayId=0 } 
    MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=681.7713, y[0]=530.18, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=2, eventTime=176267589, downTime=176267521, deviceId=2, source=0x1002, displayId=0 }
2024-03-27 11:28:58.210 6675-6675/? I/MyGesture: onScroll: 
    MotionEvent { action=ACTION_DOWN, actionButton=0, id[0]=0, x[0]=185.74203, y[0]=596.6075, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=176267521, downTime=176267521, deviceId=2, source=0x1002, displayId=0 } 
    MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=718.0028, y[0]=530.6509, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=176267593, downTime=176267521, deviceId=2, source=0x1002, displayId=0 }
2024-03-27 11:28:58.210 6675-6675/? I/MyGesture: onFling: 
    MotionEvent { action=ACTION_DOWN, actionButton=0, id[0]=0, x[0]=185.74203, y[0]=596.6075, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=176267521, downTime=176267521, deviceId=2, source=0x1002, displayId=0 } 
    MotionEvent { action=ACTION_UP, actionButton=0, id[0]=0, x[0]=718.0028, y[0]=530.6509, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=176267600, downTime=176267521, deviceId=2, source=0x1002, displayId=0 }

4: SimpleOnGestureListener类

继承SimpleOnGestureListener,代码如下:

java 复制代码
public class MyGesture2 extends GestureDetector.SimpleOnGestureListener {
    private static final String TAG = "MyGesture2";
    @Override
    public boolean onDown(MotionEvent e) {
        Log.i(TAG, "onDown:\n"+e);
        return super.onDown(e);
    }

    @Override
    public void onShowPress(MotionEvent e) {
        Log.i(TAG, "onShowPress:\n"+e);
        super.onShowPress(e);
    }

    @Override
    public boolean onSingleTapUp(MotionEvent e) {
        Log.i(TAG, "onSingleTapUp:\n"+e);
        return super.onSingleTapUp(e);
    }

    @Override
    public void onLongPress(MotionEvent e) {
        Log.i(TAG, "onLongPress:\n"+e);
        super.onLongPress(e);
    }

    @Override
    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
        Log.i(TAG, "onScroll:\n"+e1+"\n"+e2+"\n");
        return super.onScroll(e1, e2, distanceX, distanceY);
    }

    @Override
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
        Log.i(TAG, "onFling:\n"+e1+"\n"+e2+"\n");
        return super.onFling(e1, e2, velocityX, velocityY);
    }

    @Override
    public boolean onDoubleTap(MotionEvent e) {
        Log.i(TAG, "onDoubleTap:\n"+e);
        return super.onDoubleTap(e);
    }

    @Override
    public boolean onDoubleTapEvent(MotionEvent e) {
        Log.i(TAG, "onDoubleTapEvent:\n"+e);
        return super.onDoubleTapEvent(e);
    }

    @Override
    public boolean onContextClick(MotionEvent e) {
        Log.i(TAG, "onContextClick:\n"+e);
        return super.onContextClick(e);
    }

    @Override
    public boolean onSingleTapConfirmed(MotionEvent e) {
        Log.i(TAG, "onSingleTapConfirmed:\n"+e);
        return super.onSingleTapConfirmed(e);
    }

}

SimpleOnGestureListener类实际上继承了OnGestureListener, OnDoubleTapListener, OnContextClickListener这三个接口.

这里我们只需要关注OnDoubleTapListener以及OnContextClickListener即可.

  1. onSingleTapConfirmed():用户在屏幕上进行了单击操作
  2. onDoubleTap(): 发生双击时 , 参数MotionEvent代表的是第一次向下点击的事件
  3. onDoubleTapEvent():双击手势发生时发出的通知, MotionEvent可以是向下,移动,向上.
  4. onContextClick():

测试:

1.手势按下->抬起

onDown->onSingleTapUp->onSingleTapConfirmed

java 复制代码
2024-03-27 11:53:46.537 9897-9897/? I/MyGesture2: onDown:
    MotionEvent { action=ACTION_DOWN, actionButton=0, id[0]=0, x[0]=380.4716, y[0]=401.73572, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=177755922, downTime=177755922, deviceId=2, source=0x1002, displayId=0 }
2024-03-27 11:53:46.596 9897-9897/? I/MyGesture2: onSingleTapUp:
    MotionEvent { action=ACTION_UP, actionButton=0, id[0]=0, x[0]=380.4716, y[0]=401.73572, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=177755985, downTime=177755922, deviceId=2, source=0x1002, displayId=0 }
2024-03-27 11:53:46.837 9897-9897/? I/MyGesture2: onSingleTapConfirmed:
    MotionEvent { action=ACTION_DOWN, actionButton=0, id[0]=0, x[0]=380.4716, y[0]=401.73572, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=177755922, downTime=177755922, deviceId=2, source=0x1002, displayId=0 }
2: 双击

onDown->onSingleTapUp->onDoubleTap(ACTION_DOWN)->onDoubleTapEvent(ACTION_DOWN)

->onDown->onDoubleTapEvent(ACTION_MOVE)->onDoubleTapEvent(ACTION_MOVE)->onDoubleTapEvent(ACTION_UP)

java 复制代码
2024-03-24 11:48:03.028 9897-9897/? I/MyGesture2: onDown:
    MotionEvent { action=ACTION_DOWN, actionButton=0, id[0]=0, x[0]=387.46185, y[0]=547.6397, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=177412412, downTime=177412412, deviceId=2, source=0x1002, displayId=0 }
2024-03-24 11:48:03.071 9897-9897/? I/MyGesture2: onSingleTapUp:
    MotionEvent { action=ACTION_UP, actionButton=0, id[0]=0, x[0]=387.46185, y[0]=547.6397, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=177412459, downTime=177412412, deviceId=2, source=0x1002, displayId=0 }
2024-03-24 11:48:03.311 9897-9897/? I/MyGesture2: onDoubleTap:
    MotionEvent { action=ACTION_DOWN, actionButton=0, id[0]=0, x[0]=387.46185, y[0]=547.6397, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=177412412, downTime=177412412, deviceId=2, source=0x1002, displayId=0 }
2024-03-24 11:48:03.312 9897-9897/? I/MyGesture2: onDoubleTapEvent:
    MotionEvent { action=ACTION_DOWN, actionButton=0, id[0]=0, x[0]=384.46603, y[0]=527.6529, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=177412698, downTime=177412698, deviceId=2, source=0x1002, displayId=0 }
2024-03-24 11:48:03.313 9897-9897/? I/MyGesture2: onDown:
    MotionEvent { action=ACTION_DOWN, actionButton=0, id[0]=0, x[0]=384.46603, y[0]=527.6529, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=177412698, downTime=177412698, deviceId=2, source=0x1002, displayId=0 }
2024-03-24 11:48:03.332 9897-9897/? I/MyGesture2: onDoubleTapEvent:
    MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=384.46603, y[0]=527.6529, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=2, eventTime=177412715, downTime=177412698, deviceId=2, source=0x1002, displayId=0 }
2024-03-24 11:48:03.348 9897-9897/? I/MyGesture2: onDoubleTapEvent:
    MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=384.46603, y[0]=527.6529, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=2, eventTime=177412733, downTime=177412698, deviceId=2, source=0x1002, displayId=0 }
2024-03-24 11:48:03.355 9897-9897/? I/MyGesture2: onDoubleTapEvent:
    MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=384.46603, y[0]=527.6529, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=177412738, downTime=177412698, deviceId=2, source=0x1002, displayId=0 }
2024-03-24 11:48:03.356 9897-9897/? I/MyGesture2: onDoubleTapEvent:
    MotionEvent { action=ACTION_UP, actionButton=0, id[0]=0, x[0]=384.46603, y[0]=527.6529, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=177412744, downTime=177412698, deviceId=2, source=0x1002, displayId=0 }
相关推荐
花花鱼2 小时前
android studio 设置让开发更加的方便,比如可以查看变量的类型,参数的名称等等
android·ide·android studio
alexhilton3 小时前
为什么你的App总是忘记所有事情
android·kotlin·android jetpack
AirDroid_cn7 小时前
OPPO手机怎样被其他手机远程控制?两台OPPO手机如何相互远程控制?
android·windows·ios·智能手机·iphone·远程工作·远程控制
尊治7 小时前
手机电工仿真软件更新了
android
xiangzhihong89 小时前
使用Universal Links与Android App Links实现网页无缝跳转至应用
android·ios
车载应用猿10 小时前
基于Android14的CarService 启动流程分析
android
没有了遇见11 小时前
Android 渐变色实现总结
android
雨白13 小时前
Jetpack系列(四):精通WorkManager,让后台任务不再失控
android·android jetpack
mmoyula15 小时前
【RK3568 驱动开发:实现一个最基础的网络设备】
android·linux·驱动开发
sam.li16 小时前
WebView安全实现(一)
android·安全·webview