以前写 android ,对事件的处理没有太深入,只是简单的 onTouchEvent 就 ok 了,现在写的 UI ,很多自定义组件,父 view 和子view 都需要接收事件,然后处理。如果不弄明白它的事件传递机制,很难拥有好的用户体验。
Touchevent 中,返回值是 true ,则说明消耗掉了这个事件,返回值是 false ,则没有消耗掉,会继续传递下去,这个是最基本的。
在 View 中跟 Touch 相关的事件有 dispatchTouchEvent , interceptTouchEvnet , onTouchEvent 三种。 dispatchTouchEvent是负责分发事件的,事件从 activity 传递出来之后,最先到达的就是最顶层 view 的 dispatchTouchEvent ,然后它进行分发,如果返回false ,则交给这个 view 的 interceptTouchEvent 方法来决定是否要拦截这个事件,如果 interceptTouchEvent
返回 true ,也就是拦截掉了,则交给它的 onTouchEvent 来处理,如果 interceptTouchEvent 返回 false ,那么就传递给子 view ,由子 view 的dispatchTouchEvent 再来开始这个事件的分发。
如果事件传递到某一层的子 view 的 onTouchEvent 上了,这个方法返回了 false ,那么这个事件会从这个 view 往上传递,都是onTouchEvent 来接收。而如果传递到最上面的 onTouchEvent 也返回 false 的话,这个事件就会“消失”,而且接收不到下一次事件。(我说的一次事件指的是 down 到 up 之间的一系列事件)
我画了个图,见附件。
总结一下,如果这一次事件没有人消耗掉,则系统不会给你下一次事件,因为他会认为你这次的事件阻塞了,没必要给下一次。onTouchEvent如果不消耗的话,会从子view传递到父view。
又一个例子:
需求:要做一个完全通过flip手势来切换的界面。在最上层用一个ViewFlipper作为容器,并检测flip手势操作。
难题:ViewFlipper的flip手势检测需要的MotionEvent会被各种子View的触摸检测给拦截了。比如界面上有一个Button,则当手指按下Button(还没有抬起)然后flip出Button,则最上层的flip手势检测无效。
原因:android对Touch Event的分发逻辑是View从上层分发到下层(dispatchTouchEvent函数),然后下层优先开始处理Event(先mOnTouchListener,再onTouchEvent)并向上返回处理情况(boolean值),若返回true,则上层不再处理。
于是我们首先想到,要保证flip手势检测,需要把所有的Touch Event都传到上层去。
然而在分发逻辑之外还有一个逻辑,android估计是为了保证每个触操作只能由一个View来进行完整响应,对ACTION_DOWN事件有个额外的逻辑:如果某个View在处理ACTION_DOWN事件时返回false(即该View未处理此事件),那么后续产生的其它事件将直接忽略掉这个View(不过LongPress又有另外的独立逻辑)。举例来说就是,如果你处理ACTION_DOWN时返回了false,那么你这个View将得不到ACTION_MOVE或ACTION_DOWN等等这些后续事件了。
于是难题出现了,你若把Touch Event都想办法给传到上层了(只能通过返回false来传到上层),那么下层的各种子View就不能处理后续事件了。
解决方案:
开始仅着眼于Touch Event处理完后的回传过程,想了N久不得,毕竟我想实现的是一个需要打破android事件处理逻辑的效果(就是一个连续性操作,只有不满足上层要求时,才轮到下层处理)。然后突然想到事件的分发过程,便豁然开朗:
覆写最上层的View的dispatchTouchEvent函数,代码如下:
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
if (_flipDetector.onTouchEvent(event)) {
event.setAction(MotionEvent.ACTION_CANCEL);
}
return super.dispatchTouchEvent(event);
}
于是效果实现。也就是在分发之前便进行手势检测处理,若检测成功,则取消下层的一切处理过程。
分享到:
相关推荐
Android 3D模型查看器 这是OpenGL ES 2.0的演示。 这是一个带有3D引擎的Android应用程序,可以加载Wavefront OBJ,STL,DAE和glTF文件。 该应用程序基于andresoviedo的项目,可以在找到该项目,其中包含加载和呈现...
在touch或android设备上,实现用2点触控放大/缩小模型
Android 3D模型查看器 这是OpenGL ES 2.0的演示。 它基本上是一个带有3D引擎的android应用程序,可以加载Wavefront OBJ,STL和DAE文件。 该应用程序的目的是学习和共享如何使用OpenGL语言进行绘制。 该应用程序不...
允许您的用户注册物理身份验证设备(iPhone和Macs上的FaceID或TouchID,Android上的指纹,Windows上的Hello和USB密钥)以跳过输入登录凭据的操作。 允许您的用户使用FaceID / TouchID登录允许您的用户注册物理身份...
现在可以在Android上使用FaceID,TouchID和Fingerprint Reader登录。 在线演示: : 新的功能 自动登录 通过生物增强安全性 菜单和注销 暗模式和真黑 设定页面 验证服务 新页面 记住我切换 自订主题 范围模型 使用...
支持通过Sencha Touch 2来构建移动Web应用以及通过Ext JS 4来构建桌面Web应用。 其提供的代码编辑功能可以在Sencha Architect中创建整个应用。 支持模型——视图——控制器模式。 内置的针对iOS与Android的一键式...
支持通过Sencha Touch 2来构建移动Web应用以及通过Ext JS 4来构建桌面Web应用。 其提供的代码编辑功能可以在Sencha Architect中创建整个应用。 支持模型——视图——控制器模式。 内置的针对iOS与Android的一键式...
获取iOS模型使用hw.machine字符串获取iOS模型包裹 当新设备可用时,将使存储库保持更新。 如果您需要Android库,请查看我的其他仓库 。 更新: 20201212-添加了最新的iPad和iPhone型号20200404-添加了iPhone SE(第...
在 Chrome、Chrome for Android、Firefox 和 IE11 中测试 在我让这个工作之前,有相当多的实验和反复试验。 我首先创建了一个草稿界面,就像。 但这次我也确保构建一个可扩展的模型结构(您可以向样本数据添加更多...
允许您的用户注册物理身份验证设备(iPhone和Mac上为FaceID或TouchID,Android上为指纹,Windows上为Hello和USB密钥),以跳过输入其登录凭据的操作。 安装 您可以通过composer安装该软件包: composer require m1...