文档章节

Android中的事件模型

b
 byonds
发布于 2014/02/27 14:40
字数 1004
阅读 229
收藏 14

以前写 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);
      }

      于是效果实现。也就是在分发之前便进行手势检测处理,若检测成功,则取消下层的一切处理过程。


本文转载自:http://blog.csdn.net/liutao5757124/article/details/6097125

b
粉丝 0
博文 4
码字总数 0
作品 0
泉州
私信 提问
基于three.js3D模型在安卓机中事件触发问题

在three.js模型中动态添加与box模型样式一致的div,并赋予div事件touchend, 在pc浏览器和ios 中可执行,但是在安卓浏览器中事件触发不了,求解原因及解决办法。 参考http://yinhan.thewap.cn...

Seas0n_
2016/02/23
979
0
深入Android开发之--Android事件模型

前言: 一般我们处理事件,都是针对某一个View来处理了,要么是添加onTouchListener监听器,要么继承View然后重写View#onTouchEvent, 甚至不用重写,只要使用Widget自己的监听函数 ,或者GestureDe...

李海珍
2013/12/24
0
2
Android线程模型和AsyncTask

android 的线程模型:当一个 android 的应用运行后,就会有一个 UI 的 main 线程启动 , 这是一个非常重要的线程,它负责把事件分派到相应的控件,其中就包括屏幕绘图事件,它同样是用户与 an...

蜗牛TT
2012/11/06
0
0
Android 线程模型和 AsyncTask

android 的线程模型:当一个 android 的应用运行后,就会有一个 UI 的 main 线程启动 , 这是一个非常重要的线程,它负责把事件分派到相应的控件,其中就包括屏幕绘图事件,它同样是用户与 an...

华宰
2011/07/27
17.1K
8
WP7和Android对比 - 执行模型和生命周期

对于开发过Android应用的WP7开发者来说,有了Android的基础理解Windows Phone应用程序的执行模型和生命周期就变得很轻松了,下面就应用的生命周期做简单的对比: 在Android应用中入口点是App...

鉴客
2012/02/24
356
0

没有更多内容

加载失败,请刷新页面

加载更多

前嗅教程:如何获取精准客源,提高销量

经常有人问嗅嗅,我是XX行业的,大数据能帮我做什么? • 可以给我带来客源吗? • 可以提高我的销量吗? • 可以增加我的利润吗? 今天嗅嗅就以生鲜供货为例,为大家讲一讲外卖平台那些事~...

forespider
28分钟前
1
0
浮窗插件

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>移动窗口</title> <style> body { margin: 0; padding: 0; width: 100%; height: 1000px; background: #eee; } /*示......

流年那么伤
32分钟前
2
0
关于 Jenkins master 共享 JENKINS_HOME 目录的实验

本文首发于:Jenkins 中文社区 作者:翟志军 审校:王冬辉,linuxsuren Jenkins master 的高可用是个老大难的问题。和很多人一样,笔者也想过两个 Jenkins master 共享同一个 JENKINS_HOME 的...

Jenkins中文社区
39分钟前
3
0
【重构】Spring Cloud OAuth 无Token调用源码封装

背景 重构-改善既有代码的设计,重构的目的是是软件更容易被理解和修改。 书接上回Spring Security OAuth 微服务内部Token传递的源码解析,本篇主要无token 调用过程中,代码的不断完善及其重...

冷冷gg
45分钟前
26
0
watchOS更新后 Apple Watch 4心电图功能已开始支持欧洲用户

苹果在发布 Apple Watch 4 系列时也发布了 ECG(心电图)功能,但这项功能仅适用于在美版 Apple Watch。对于其他地区的用户来说,访问该功能的唯一途径是在美国购买该设备。不过当 watchOS ...

linuxCool
54分钟前
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部