★60.自定义控件 ★19.MotionEvent详解dd

单点触控

事件表

事件 简介
ACTION_DOWN 手指 初次接触到屏幕 时触发。
ACTION_MOVE 手指 在屏幕上滑动 时触发,会多次触发。
ACTION_UP 手指 离开屏幕 时触发。
ACTION_CANCEL 事件 被上层拦截 时触发。
ACTION_OUTSIDE 手指 不在控件区域 时触发

方法表

方法 简介
getAction() 获取 事件类型 。
getX() 获得 触摸点 在当前View的 X坐标 。
getY() 获得 触摸点 在当前View的 Y坐标 。
getRawX() 获得 触摸点 在整个屏幕的 X坐标 。
getRawY() 获得 触摸点 在整个屏幕的 Y坐标 。

简单示例

@Override
public boolean onTouchEvent(MotionEvent event) {
    switch (event.getAction()){
        case MotionEvent.ACTION_DOWN:
            // 手指按下
            break;
        case MotionEvent.ACTION_MOVE:
            // 手指移动
            break;
        case MotionEvent.ACTION_UP:
            // 手指抬起
            break;
        case MotionEvent.ACTION_CANCEL:
            // 事件被拦截
            break;
        case MotionEvent.ACTION_OUTSIDE:
            // 超出区域
            break;
    }
    return super.onTouchEvent(event);
}

ACTION_CANCEL

  • 触摸事件流程 :ACTION_DOWN -> ACTION_MOVE -> ACTION_UP。
  • 触摸事件流程中间 :已经接收到ACTION_DOWN事件,但是还没有接收到ACTION_UP事件。
  • 子View在 触摸事件流程中间 时,父View拦截了触摸事件,此时子View会接收到ACTION_CANCEL事件。

ACTION_OUTSIDE

  • ACTION_OUTSIDE不是在View内部滑动到外部的时候产生的。
  • ACTION_OUTSIDE用于Dialog这样的特殊窗口,使其能够接收到视图区域外的事件。
  • 默认情况下,无法接收到ACTION_OUTSIDE,需要设置视图的WindowManager布局参数的flags为FLAG_WATCH_OUTSIDE_TOUCH。
  • 除了Dialog之外,最可能看到ACTION_OUTSIDE的场景是 悬浮窗 。

多点触控

简介

  • 发生 多点触控 时,最先接收到的 触摸点 作为 主触摸点 ,之后接收到的 触摸点 作为 辅助触摸点 。

触摸点索引 与 触摸点ID

  • 单次触摸事件 :ACTION_DOWN、ACTION_UP、ACTION_MOVE。
  • 触摸事件流程 :ACTION_DOWN -> ACTION_MOVE -> ACTION_UP。
  • 触摸点索引 与 触摸点ID 都是用于标识 触摸点 ,但是:
    • 触摸点索引 只保证在 单次触摸事件 有效。
    • 触摸点ID 能保证在整个 触摸事件流程 有效。
    • 通常使用 触摸点ID 来标识 触摸点 ,而不是 触摸点索引 。

事件表

事件 简介
ACTION_DOWN 第一个 手指 初次接触到屏幕 时触发。
ACTION_MOVE 手指 在屏幕上滑动 时触发,会多次触发。
ACTION_UP 最后一个 手指 离开屏幕 时触发。
ACTION_POINTER_DOWN 有其他手指按下( 即按下之前已经有手指在屏幕上 )。
ACTION_POINTER_UP 有其他手指抬起( 即抬起之后仍然有手指在屏幕上 )。

方法表

方法 简介
getActionMasked() 获取 事件类型 。
getActionIndex() 获取 触摸点索引 。
getPointerCount() 获取 触摸点 个数。
getPointerId(int pointerIndex) 使用 触摸点索引 获取 触摸点ID 。
findPointerIndex(int pointerId) 使用 触摸点ID 获取 触摸点索引 。
getX(int pointerIndex) 获取 触摸点索引 对应的 X坐标 。
getY(int pointerIndex) 获取 触摸点索引 对应的 Y坐标 。

getAction() 与 getActionMasked()

  • 多点触控 使用getActionMasked()来获取 事件类型 。
  • 单点触控 使用getAction()(或getActionMasked())来获取 事件类型 。

移动事件历史

简介

  • 移动事件历史 :由于ACTION_MOVE事件的产生十分频繁,为了提高性能,会将多个ACTION_MOVE事件打包放进同一个MotionEvent中批量处理。
  • 单点触控 和 多点触控 都可以用 移动事件历史 。

方法表

事件 简介
getHistorySize() 获取 移动事件历史集合 大小。
getHistoricalX(int pos) 获取第pos个的 移动事件历史 的 X坐标 。
getHistoricalY(int pos) 获取第pos个的 移动事件历史 的 Y坐标 。
getHistoricalX(int pointerIndex, int pos) 获取 触摸点索引 对应的第pos个 移动事件历史 的 X坐标 。
getHistoricalY(int pointerIndex, int pos) 获取 触摸点索引 对应的第pos个 移动事件历史 的 Y坐标 。

触摸事件时间

方法 简介
getDownTime() 获取手指按下时的时间,单位为 毫秒 。
getEventTime() 获取当前事件发生的时间,单位为 毫秒 。
getHistoricalEventTime(int pos) 获取第pos个 移动事件历史 发生的时间,单位为 毫秒 。

触摸面积 与 触摸压力

简介

  • 触摸面积 识别和 触摸压力 识别是需要硬件支持的。
  • 目前,大部分设备的屏幕不支持识别 触摸压力 ,但能够大致识别 触摸面积 。
  • 大部分设备是使用 触摸面积 来模拟 触摸压力 的。

方法表

方法 简介
getSize() 获取 触摸面积 。
getSize(int pointerIndex) 获取 触摸点索引 对应的 触摸面积 。
getHistoricalSize(int pos) 获取第pos次 移动事件历史 的 触摸面积 。
getHistoricalSize(int pointerIndex, int pos) 获取 触摸点索引 对应的第pos次 移动事件历史 的 触摸面积 。
getPressure() 获取 触摸压力 。
getPressure(int pointerIndex) 获取 触摸点索引 对应的 触摸压力 。
getHistoricalPressure(int pos) 获取第pos次 移动事件历史 的 触摸压力 。
getHistoricalPressure(int pointerIndex, int pos) 获取 触摸点索引 对应的第pos次 移动事件历史 的 触摸压力 。

滑动冲突处理

  1. RecyclerView收到了一个ACTION_DOWN事件,先假定是个点击事件,传递给对应ItemView,询问ItemView是否需要这个事件。
  2. 接着,RecyclerView收到一个ACTION_MOVE事件,且移动的方向和RecyclerView的可滑动方向一致,此时可以判断这个事件是 滚动事件 ,因此进行 拦截 。
  3. 因为上层View进行了 拦截 ,所以对应的ItemView会收到一个 ACTION_CANCEL ,并且不会再收到后续事件。
最后编辑于 :
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容