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 }
相关推荐
H1001 小时前
重构(二)
android·重构
拓端研究室1 小时前
R基于贝叶斯加法回归树BART、MCMC的DLNM分布滞后非线性模型分析母婴PM2.5暴露与出生体重数据及GAM模型对比、关键窗口识别
android·开发语言·kotlin
zhangphil2 小时前
Android简洁缩放Matrix实现图像马赛克,Kotlin
android·kotlin
m0_512744642 小时前
极客大挑战2024-web-wp(详细)
android·前端
lw向北.2 小时前
Qt For Android之环境搭建(Qt 5.12.11 Qt下载SDK的处理方案)
android·开发语言·qt
不爱学习的啊Biao2 小时前
【13】MySQL如何选择合适的索引?
android·数据库·mysql
Clockwiseee3 小时前
PHP伪协议总结
android·开发语言·php
mmsx9 小时前
android sqlite 数据库简单封装示例(java)
android·java·数据库
众拾达人12 小时前
Android自动化测试实战 Java篇 主流工具 框架 脚本
android·java·开发语言
吃着火锅x唱着歌13 小时前
PHP7内核剖析 学习笔记 第四章 内存管理(1)
android·笔记·学习