最近新闻列表里的下拉 down up  move 等等让我十分头疼 ,无意间看到了一篇非常不错的帖子,转载如下:

开篇语:最近程序在做一个小效果,要用到touch,结果整得云里面雾里的,干脆就好好把android touch机制好好看了一下,呵呵。。

android系统中的每个ViewGroup的子类都具有下面三个和TouchEvent处理密切相关的方法:

1)public boolean dispatchTouchEvent(MotionEvent ev)          这个方法用来分发TouchEvent

2)public boolean onInterceptTouchEvent(MotionEvent ev)         这个方法用来拦截TouchEvent

3)public boolean onTouchEvent(MotionEvent ev)                 这个方法用来处理TouchEvent

注意:不是所有的View的子类,很多教程都说的是所有的View的子类,只有可以向里面添加View的控件才需要分发,比如TextView它本身就是最小的view了,所以不用再向它的子视图分发了,它也没有子视图了,所以它没有dispatch和Intercept,只有touchEvent。

说明: 白色为最外层,它占满整个屏幕;

红色为中间区域,属于白色中的一层;

黑色为中心区域,必于红色中的一层。

注意:他们本质上是:LinearLayout,而不是RelativeLayout或者其它布局。

1.由中心区域处理touch事件

布局文件如下:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:layout_width="fill_parent"
  4. android:layout_height="fill_parent"
  5. android:orientation="vertical">
  6. <com.kris.touch.widget.TouchView
  7. android:id="@+id/view_out"
  8. android:layout_width="fill_parent"
  9. android:layout_height="fill_parent"
  10. android:background="#fff"
  11. android:gravity="center">
  12. <com.kris.touch.widget.TouchView
  13. android:id="@+id/view_mid"
  14. android:layout_width="300px"
  15. android:layout_height="400px"
  16. android:background="#f00"
  17. android:gravity="center">
  18. <com.kris.touch.widget.TouchView
  19. android:id="@+id/view_center"
  20. android:layout_width="150px"
  21. android:layout_height="150px"
  22. android:background="#000"
  23. android:gravity="center"
  24. android:clickable="true">
  25. </com.kris.touch.widget.TouchView>
  26. </com.kris.touch.widget.TouchView>
  27. </com.kris.touch.widget.TouchView>
  28. </LinearLayout>

复制代码

注意:                android:clickable="true"  

接下来我们看一下打印的日志:

结合是上面的日志,我们可以看一下ACTION_DOWN事件处理流程:

说明:

首先触摸事件发生时(ACTION_DOWN),由系统调用Activity的dispatchTouchEvent方法,分发该事件。根据触摸事件的坐标,将此事件传递给out的dispatchTouchEvent处理,out则调用onInterceptTouchEvent 判断事件是由自己处理,还是继续分发给子View。此处由于out不处理Touch事件,故根据事件发生坐标,将事件传递给out的直接子View(即middle)。

Middle及Center中事件处理过程同上。但是由于Center组件是clickable 表示其能处理Touch事件,故center中的onInterceptTouchEvent方法将事件传递给center自己的onTouchEvent方法处理。至此,此Touch事件已被处理,不继续进行传递。

2.没有指定谁会处理touch事件

布局文件如下:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:layout_width="fill_parent"
  4. android:layout_height="fill_parent"
  5. android:orientation="vertical">
  6. <com.kris.touch.widget.TouchView
  7. android:id="@+id/view_out"
  8. android:layout_width="fill_parent"
  9. android:layout_height="fill_parent"
  10. android:background="#fff"
  11. android:gravity="center">
  12. <com.kris.touch.widget.TouchView
  13. android:id="@+id/view_mid"
  14. android:layout_width="300px"
  15. android:layout_height="400px"
  16. android:background="#f00"
  17. android:gravity="center">
  18. <com.kris.touch.widget.TouchView
  19. android:id="@+id/view_center"
  20. android:layout_width="150px"
  21. android:layout_height="150px"
  22. android:background="#000"
  23. android:gravity="center">
  24. </com.kris.touch.widget.TouchView>
  25. </com.kris.touch.widget.TouchView>
  26. </com.kris.touch.widget.TouchView>
  27. </LinearLayout>

复制代码

注意:只是比上一次的布局少了android:clickable="true" 
接下来我们看一下打印的日志

结合是上面的日志,我们可以看一下ACTION_DOWN事件处理流程:

说明:

事件处理流程大致同上,区别是此状态下,所有组件都不会处理事件,事件并不会被center的onTouchEvent方法“消费”,则事件会层层逆向传递回到Activity,若Activity也不对此事件进行处理,此事件相当于消失了(无效果)。

对于后续的move、up事件,由于第一个down事件已经确定由Activity处理事件,故up事有由Activity的dispatchTouchEvent直接分发给自己的onTouchEvent方法处理。

代码请看最后的附件

总结:

1) Touchevent 中,返回值是 true ,则说明消耗掉了这个事件,返回值是 false ,则没有消耗掉,会继续传递下去,这个是最基本的。2) 事件传递的两种方式: 
隧道方式:从根元素依次往下传递直到最内层子元素或在中间某一元素中由于某一条件停止传递。 
冒泡方式:从最内层子元素依次往外传递直到根元素或在中间某一元素中由于某一条件停止传递。 android对Touch Event的分发逻辑是View从上层分发到下层(dispatchTouchEvent函数)类似于隧道方式,然后下层优先开始处理Event(先mOnTouchListener,再onTouchEvent)并向上返回处理情况(boolean值),若返回true,则上层不再处理。类似于冒泡方式 
于是难题出现了,你若把Touch Event都想办法给传到上层了(只能通过返回false来传到上层),那么下层的各种子View就不能处理后续事件了。而有的时候我们需要在下层和上层都处理Touch事件

举个例子,ViewFlipper用来检测手势,在内部我们放几个Image,有点像gallery的效果,也就是左右滑动切换图片,但是图片有时候我们希望可以放大缩小!这样就会存在ViewFlipper里面需要touch事件,而在image里面也需要一个touch事件(当图片大小屏幕边界的时候可以拖动图片,而不是左右切换图片)。

我首先的思路是着手于事件回传的方式,研究了n久,实际了n久,都没达到自己想要的结果 ,我甚至于把gallery和gallery3D 的源码下载下来看了N久也没办法去解决,在这里随便说一下gallery吧,gallery虽然在这个效果,但是人家并不是ViewFlipper加image这样来实现的,人家是像游戏这样用一个view来统一处理的,我们可以简单的理解成自定义了一个控件,这样touch事件想怎么处理就怎么处理,不过就是逻辑复杂了,我们想偷懒就没办法了,呵呵。。。

最后不停的试啊试啊,想到一个可行的方案,但是我觉得不是很靠谱,也就是:我们在ViewFlipper这里,我们先把所有的touch都截取到,然后在他的onTouchEvent中,我们先调用imageview的onTouchEvent事件,如果返回true,证明这个事件,imageview要用,那么ViewFlipper就当什么事都没发生,如果imageview返回的false,则调用自己的touchEvent.伪代码如下:

  1. //自定义一个MyViewFlipper 继承于ViewFlipper,并且实现onTouchEvent方式,

复制代码

我觉得他不靠谱的原因为: 1. 他打断了android的原有的机制,不是很提倡。 
2. 得试先知道ViewFlipper里面的控件,或者说通过某种路径能获取到 
3. 如果ViewFlipper里面的控件多了,就蛋疼了

好了,如果有什么意见或者建议,大家一起讨论。

原文链接:http://www.cnblogs.com/jqyp/archive/2012/04/25/2469758.html

Android Touch事件传递机制解析 (推荐)的更多相关文章

  1. Android Touch事件传递机制解析

    android系统中的每个ViewGroup的子类都具有下面三个和TouchEvent处理密切相关的方法: 1)public boolean dispatchTouchEvent(MotionEven ...

  2. Android Touch事件传递机制 二:单纯的(伪生命周期)

    转载于:http://blog.csdn.net/yuanzeyao/article/details/38025165 在前一篇文章中,我主要讲解了Android源码中的Touch事件的传递过程,现在 ...

  3. Android Touch事件传递机制 一: OnTouch,OnItemClick(监听器),dispatchTouchEvent(伪生命周期)

      ViewGroup View  Activity dispatchTouchEvent 有 有 有 onInterceptTouchEvent 有 无 无 onTouchEvent 有 有 有 例 ...

  4. Android touch 事件传递机制

    前言: (1)在自定义view的时候经常会遇到事件拦截处理,比如在侧滑菜单的时候,我们希望在侧滑菜单里面有listview控件,但是我们希望既能左右滑动又能上下滑动,这个时候就需要对触摸的touch事 ...

  5. Android Touch事件传递机制通俗讲解

    在讲正题之前我们讲一段有关任务传递的小故事,抛砖迎玉下: 话说一家软件公司,来一个任务,分派给了开发经理去完成: 开发经理拿到,看了一下,感觉好简单,于是 开发经理:分派给了开发组长 开发组长:分派给 ...

  6. Android Touch事件传递机制 二:单纯的(伪生命周期) 这个清楚一点

    转载于:http://blog.csdn.net/yuanzeyao/article/details/38025165 在前一篇文章中,我主要讲解了Android源码中的Touch事件的传递过程,现在 ...

  7. Android Touch事件传递机制引发的血案

    尊重原创:http://blog.csdn.net/yuanzeyao/article/details/38942135 关于Android Touch事件传递机制我之前也写过两篇文章,自觉得对Tou ...

  8. Android Touch事件传递机制详解 下

    尊重原创:http://blog.csdn.net/yuanzeyao/article/details/38025165 资源下载:http://download.csdn.net/detail/yu ...

  9. Android Touch事件传递机制具体解释 下

    尊重原创:http://blog.csdn.net/yuanzeyao/article/details/38025165 资源下载:http://download.csdn.net/detail/yu ...

随机推荐

  1. iOS设计模式 - 命令模式

    前言: 命令对象封装了如何对目标执行指令的信息,因此客户端或调用者不必了解目标的任何细节,却仍可以对他执行任何已有的操作.通过把请求封装成对象,客 户端可 以把它参数化并置入队列或日志中,也能够支持可 ...

  2. 用Qt开发第一个Hello World程序

    配置好Qt的环境变量之后,我们才可以进行下面的通过终端来使用Qt开发这个第一个程序 因为Qt的文件路径不能有中文否则会报错,所以一般都把工程文件都建立在根目录 我们创建的Qt程序包含两个部分:1.GU ...

  3. vs2012远程调试功能的改进

    不知道大家有没有遇到过这种情况,刚开发完的程序,明明在本机能够好好的运行,可是部署到服务器过分发给用户时,总是出现莫名其妙的错误. 一时半会又看不出问题来,怎么办呢?难道只能在服务器或是客户电脑上装一 ...

  4. Asp.net MVC 4新项目中创建area的后续操作

    Asp.net MVC 4新项目中创建area后,往往HomeController与area的HomeController路由发生混淆,需要手工设置一些地方避免mvc无法识别默认路由的状况. 无废话具 ...

  5. virtualbox 安装 虚拟机的时候报错不能创建新任务

    找到原因是因为自己的windows是破解的, 找到C:\Windows\system32\uxtheme.dll这个文件,我的破解的windows在这里自带了一个uxtheme.dll.backup的 ...

  6. MySQL 中的 FOUND_ROWS() 与 ROW_COUNT() 函数

    移植sql server 的存储过程到mysql中,遇到了sql server中的: IF @@ROWCOUNT < 1 对应到mysql中可以使用 FOUND_ROWS() 函数来替换. 1. ...

  7. js中location.href的用法

    Javascript中的location.href有很多种用法,主要如下: self.location.href="/url" 当前页面打开URL页面 ocation.href=& ...

  8. 通过java来批量生成身份证号

    通过java来批量生成身份证号,方便来测试程序. package com.diyvc.controller.user; import java.util.Calendar; import java.u ...

  9. nyoj 1029/hdu 3714 Error Curves 三分

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3714 懂了三分思想和F(x)函数的单调性质,这题也就是水题了 #include "stdio ...

  10. 再学TSQL基础--单表查询

    本内容是我学习tsql2008的阅读笔记 什么是关系模型? 若对列创建唯一约束,背后中的物理机制也是创建了一个唯一索引. SQL语句的逻辑解析顺序是FROM WHERE GROUP BY HAVING ...