Android MotionEvent 详解,之前用了两篇文章 事件分发机制原理 和 事件分发机制详解 来讲解事件分发,而作为事件分发主角之一的 MotionEvent 并没有过多的说明,本文就带大家了解 MotionEvent 的相关内容,简要介绍触摸事件,主要包括 单点触控、多点触控、鼠标事件 以及 getAction() 和 getActionMasked() 的区别。

Android 将所有的输入事件都放在了 MotionEvent 中,随着安卓的不断发展壮大,MotionEvent 也开始变得越来越复杂,下面是我自己整理的 MotionEvent 大事记:

版本号 更新内容
Android 1.0 (API 1 ) 支持单点触控和轨迹球的事件。
Android 1.6 (API 4 ) 支持手势。
Android 2.0 (API 5 ) 支持多点触控。
Android 3.1 (API 12) 支持触控笔,鼠标,键盘,操纵杆,游戏控制器等输入工具。

以上仅仅是简要的说明几次比较大的变动,细小的修复和更新不计其数,此处就不一一列出了,反正也没人关心这些东西。
MotionEvent 负责集中处理所有类型设备的输入事件,但是由于某些设备使用的几率较小本文会忽略讲解,或者简要讲解,例如:
1、轨迹球只出现在最早的设备上,现代的设备上已经见不到了,本文不再叙述。
2、触控笔和手指处理流程基本相同,不再多说。
3、鼠标在手机上使用概率也比较小,会在文末简要介绍。

单点触控

单点触控就非常简单啦,入门的工程师都会用,上一篇文章也简要介绍过,主要涉及以下几个事件:

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

和以下的几个方法:

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

关于 getgetRaw 的区别可以参考这一篇文章 安卓自定义View基础-坐标系

单点触控一次简单的交互流程是这样的:

手指落下(ACTION_DOWN) -> 多次移动(ACTION_MOVE) -> 离开(ACTION_UP)

  • 本次事例中 ACTION_MOVE 有多次触发。
  • 如果仅仅是单击(手指按下再抬起),不会触发 ACTION_MOVE。

针对单点触控的事件处理一般是这样写的:

@Override
public boolean onTouchEvent(MotionEvent event) {// ▼ 注意这里使用的是 getAction(),先埋一个小尾巴。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_CANCELACTION_OUTSIDE
为什么说特殊呢,因为它们是由程序触发而产生的,而且触发条件也非常特殊,通常情况下即便不处理这两个事件也没有什么问题。接下来我们就扒一扒它们的真面目:

ACTION_CANCEL

ACTION_CANCEL 的触发条件是事件被上层拦截,然而我们在 事件分发机制原理 一文中了解到当事件被上层 View 拦截的时候,ChildView 是收不到任何事件的,ChildView 收不到任何事件,自然也不会收到 ACTION_CANCEL 了,所以说这个 ACTION_CANCEL 的正确触发条件并不是这样,那么是什么呢?

事实上,只有上层 View 回收事件处理权的时候,ChildView 才会收到一个 ACTION_CANCEL 事件。

这样说可能不太容易理解,咱举个例子?

例如:上层 View 是一个 RecyclerView,它收到了一个 ACTION_DOWN 事件,由于这个可能是点击事件,所以它先传递给对应 ItemView,询问 ItemView 是否需要这个事件,然而接下来又传递过来了一个 ACTION_MOVE 事件,且移动的方向和 RecyclerView 的可滑动方向一致,所以 RecyclerView 判断这个事件是滚动事件,于是要收回事件处理权,这时候对应的 ItemView 会收到一个 ACTION_CANCEL ,并且不会再收到后续事件。

通俗一点?

RecyclerView:儿砸,这里有一个 ACTION_DOWN 你看你要不要。
ItemView :好嘞,我看看。
RecyclerView:噫?居然是移动事件ACTION_MOVE,我要滚起来了,儿砸,我可能要把你送去你姑父家(缓存区)了,在这之前给你一个 ACTION_CANCEL,你要收好啊。
ItemView :……

这是实际开发中最有可能见到 ACTION_CANCEL 的场景了。

ACTION_OUTSIDE

ACTION_OUTSIDE的触发条件更加奇葩,从字面上看,outside 意思不就是超出区域么?然而不论你如何滑动超出控件区域都不会触发 ACTION_OUTSIDE 这个事件。相信很多魔法师都对此很是疑惑,说好的超出区域呢?

实际上这个事件根本就不是在这里用的,看官方解释(装一下逼):

A movement has happened outside of the normal bounds of the UI element. This does not provide a full gesture, but only the initial location of the movement/touch.

一个触摸事件已经发生了UI元素的正常范围之外。因此不再提供完整的手势,只提供 运动/触摸 的初始位置。

我们知道,正常情况下,如果初始点击位置在该视图区域之外,该视图根本不可能会收到事件,然而,万事万物都不是绝对的,肯定还有一些特殊情况,你可曾还记得点击 Dialog 区域外关闭吗?Dialog 就是一个特殊的视图(没有占满屏幕大小的窗口),能够接收到视图区域外的事件(虽然在通常情况下你根本用不到这个事件),除了 Dialog 之外,你最可能看到这个事件的场景是悬浮窗,当然啦,想要接收到视图之外的事件需要一些特殊的设置。

设置视图的 WindowManager 布局参数的 flags为[FLAG_WATCH_OUTSIDE_TOUCH](http://developer.android.com/reference/android/view/WindowManager.La

续集:

  • Android自定义控件进阶01-自定义控件开发套路与流程
  • Android自定义控件进阶02-Canvas之绘制图形
  • Android自定义控件进阶03-Canvas之画布操作
  • Android自定义控件进阶04-Canvas之图片文字
  • Android自定义控件进阶05-Path之基本操作
  • Android自定义控件进阶06-Path之贝塞尔曲线
  • Android自定义控件进阶07-Path之完结篇
  • Android自定义控件进阶08-PathMeasure详解
  • Android自定义控件进阶09-控件核心Matrix原理
  • Android自定义控件进阶10-控件核心Matrix Camera
  • Android自定义控件进阶11-事件分发机制原理
  • Android自定义控件进阶11-事件分发机制原理01
  • Android自定义控件进阶12-事件分发机制原理02
  • Android自定义控件进阶13-MotionEvent详解
  • Android自定义控件进阶14-特殊控件的事件处理方案

粉丝技术交流扣裙

Android自定义控件进阶13-MotionEvent详解相关推荐

  1. Android自定义控件系列八:详解onMeasure()(二)--利用onMeasure测量来实现图片拉伸永不变形,解决屏幕适配问题

    上一篇文章详细讲解了一下onMeasure/measure方法在Android自定义控件时的原理和作用,参看博文:Android自定义控件系列七:详解onMeasure()方法中如何测量一个控件尺寸( ...

  2. Android 多点触控 MotionEvent详解

    相关API 介绍 MotionEvent.getY() 和 MotionEvent.getRawY() 的区别 getY 表示触摸事件在当前的View内的Y 坐标, getRawY表示触摸事件在整个屏 ...

  3. Android自定义View进阶-MotionEvent详解

    欢迎Follow我的GitHub, 关注我的CSDN. 其余参考Android目录 我们微信公众号:杨守乐 推荐文章: 如果你喜欢上了一个程序员小伙,献给所有的程序员女友 学习资料(干货汇集)不断更新 ...

  4. android鼠标滚轮事件坐标,Android触摸滑动全解(四)——MotionEvent详解

    Android触摸滑动全解(四)--MotionEvent详解 在分析View和ViewGroup的触摸事件时,我们已经接触到了MotionEvent类,它是用来存储我们当前手指移动的状态的,比如按下 ...

  5. Android自定义控件进阶12-事件分发机制原理

    Android 事件分发机制详解,在上一篇文章 事件分发机制原理 中简要分析了一下事件分发机制的原理,原理是十分简单的,一句话就能总结:责任链模式,事件层层传递,直到被消费. 虽然原理简单,但是随着 ...

  6. 【备注】【C24】《Android 3D游戏开发技术详解与典型案例》PDF 下载

    [C24]<Android 3D游戏开发技术详解与典型案例>PDF 下载 目前市面上的Android技术书籍还比较少,Android3D游戏开发的书籍更是没有.因此,在现在市面上,Andr ...

  7. Android高效率编码-第三方SDK详解系列(一)——百度地图,绘制,覆盖物,导航,定位,细腻分解!

    Android高效率编码-第三方SDK详解系列(一)--百度地图,绘制,覆盖物,导航,定位,细腻分解! 这是一个系列,但是我也不确定具体会更新多少期,最近很忙,主要还是效率的问题,所以一些有效的东西还 ...

  8. Android自定义控件进阶03-Canvas之画布操作

    Android自定义控件进阶03-Canvas之画布操作 本来想把画布操作放到后面部分的,但是发现很多图形绘制都离不开画布操作,于是先讲解一下画布的基本操作方法. 一.Canvas的常用操作速查表 操 ...

  9. android+发邮件,Android发送邮件的方法实例详解

    Android发送邮件的方法实例详解 时间:2021-05-20 本文实例讲述了Android发送邮件的方法.分享给大家供大家参考,具体如下: 在android手机中实现发送邮件的功能也是不可缺少的. ...

最新文章

  1. Lumen报class does not exist的mailer坑
  2. 消除 activity 启动时白屏、黑屏问题
  3. 【C++】【二】动态数组-Dynamic_linklist
  4. 利用Excel导入数据到SAP C4C
  5. 统计单词出现的次数并进行排
  6. BugkuCTF-MISC题赛博朋克
  7. 最简单的YUV422转jpg的例程
  8. mac nginx 指定php.ini,基于Mac自带nginx、php,配置php运行环境
  9. python中的fun_Python fun中*args,**kwargs参数的含义和用法(*args,**kwargs),Pythonfunargskwargs,及...
  10. normalize.css下载
  11. 89C51最小系统典型应用
  12. Acmer--弱水三千,只取一瓢
  13. c语言 main()可否省略,main函数中省略返回语句
  14. 树莓派4B简单使用内容(以移植QT应用为例)
  15. Revit翻模教程:怎么在体量内绘制圆锥?
  16. 聊天机器人chatbot搭建及思考(TensorFlow)(附代码)
  17. 【有利可图网】PS实战系列:制作饼干字特效
  18. 2018年区块链十大发展势头
  19. python控制网络摄像头_用Python控制摄像头拍照并发邮件
  20. ma5822是什么设备_MA5822 配置二层交换

热门文章

  1. Python和Excel终于互通了!这个Jupyter插件能自动生成代码并实现数据分析
  2. GitHub安装(Windows)
  3. 谷歌地图 API 的 5 个强大替代品(国外产品)
  4. netlink 读取数据流程
  5. 详解clientWidth,scrollWidth,offsetWidth,innerWidth,outerWidth
  6. html的概念及扩展名
  7. 一句话解释Dubbo服务本地暴露和远程暴露
  8. Ubuntu 通过无线 连PPPOE的 上网
  9. 走近所罗门 Part 1 邮件中的所罗门
  10. 大数据学习过程笔记——第一阶段