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 }
相关推荐
v***913017 分钟前
Spring+Quartz实现定时任务的配置方法
android·前端·后端
wilsend31 分钟前
Android Studio 2024版新建java项目和配置环境下载加速
android
兰琛1 小时前
Android Compose展示PDF文件
android·pdf
走在路上的菜鸟2 小时前
Android学Dart学习笔记第四节 基本类型
android·笔记·学习
百锦再2 小时前
第21章 构建命令行工具
android·java·图像处理·python·计算机视觉·rust·django
skyhh4 小时前
Android Studio 最新版汉化
android·ide·android studio
路人甲ing..4 小时前
Android Studio 快速的制作一个可以在 手机上跑的app
android·java·linux·智能手机·android studio
携欢7 小时前
PortSwigger靶场之Web shell upload via path traversal靶场通关秘籍
android
消失的旧时光-194314 小时前
Android ADB指令大全详解
android·adb
ashcn200117 小时前
opengl 播放视频的android c++ 方案
android·c++ opengl es