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

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

更多相关文章

  1. Android(安卓)UI 滚动、手势、速度的三个帮助类学习
  2. Android退出程序(二)——利用广播机制
  3. Android基础知识(2)—事件处理
  4. 2.4简单的按钮----Android(安卓)Button
  5. Android学习之使用SAX解析xml文件
  6. Android(安卓)RxJava 实际应用讲解:联合判断多个事件
  7. android回调接口的两种方式
  8. Android招财进宝手势密码的实现
  9. Android(安卓)sax解析XML数据

随机推荐

  1. SQL语句练习实例之二——找出销售冠军
  2. SQL语句练习实例之三——平均销售等待时
  3. SQL Server Bulk Insert 只需要部分字段
  4. SQL 判断给定日期值(或时间段)所在星期的
  5. 在数据库‘master’中拒绝CREATE DATABAS
  6. mssql server 数据库附加不上解决办法分
  7. Android开发中遇到的坑
  8. Android(安卓)数据业务框架分析
  9. Buttons in button bars should be borde
  10. [Android(安卓)L]关于Android(安卓)L的Se