当我们手指按下时,Android采用层层传递-冒泡的方式处理点击事件。例如,现在公司来了个小项目,老板一看分配给经理做,经理一看分配给小组长,小组长一看好简单,分配给组员。如果在这个传递过程中(也就是还为分配到最底部时),某一层觉得我来负责这个比较好的话就会拦截掉这个消息,然后把它处理了,下面的就收不到有消息的这个通知。如果一直到了底层的话,组员如果能完成,就完成它。如果不能完成,那么就报告给组长,说组长我做不来,边学边做要影响进度。组长一看我也做不来,就给经理,经理一看我也不会,就给老板。这样也就一层层的传递了。 
      以上的意思也即:消息从上到下依次传递,如果在传递的过程中被拦截了就停止下传。如果没有被拦截,就一直传递到底部,如果底部不能够消耗该消息,那么就又一层层的返回来,返给上层,直到被消耗或者是到达最顶层。在此过程中,存在三个重要的方法:

    dispathTouchEvent(MotionEvent ev)  
负责事件的分发,它的返回值就是表示是否消耗当前事件;
onInterceptTouchEvent(MotionEvent ev)
用于判断是否拦截该消息,如果当前View拦截了某个时间,那么在同一个事件序列中,此方法不会被再次调用。返回结果表示是否拦截当前事件 。
onTouchEvent(MotionEvent ev)
处理事件。返回结果表示是否消耗当前事件,如果不消耗,则在同一时间序列中,当前View无法再次接收到事件。

对于一个根ViewGroup来说,点击事件产生后,首先会传递给它,并调用它的dispath方法。如果这个ViewGroup的onIntercept方法返回true就表示它要拦截当前事件,false就表示不拦截,这个时候事件就会继续传递给子元素,接着调用子元素的dispath方法,一直重复以上过程到事件被处理。

下面介绍一下常见的问题及解决方法:

一、滑动冲突

View的滑动冲突产生愿意大概可以分为三种:

  • 外部滑动和内部滑动方向不一致
  • 外部滑动方向和内部滑动方向一致
  • 嵌套上面两种情况

比如说一个常见的,外部一个ListView,里面一个ScrollView,滑动时出现冲突?

此时一般是采用外部拦截法(即结合onInterceptTouchEvent、onTouchEvent)来进行解决。具体方法如下:

   (1)外部拦截法

      外部拦截法就是指所有的点击时间都经过父容器的拦截处理,如果父容器需要此事件就拦截,如果不需要此事件就不拦截。通过重写父容器的onInterceptTouchEvent方法:

 case MotionEvent.ACTION_DOWN:
intercepted = false;
break;
case MotionEvent.ACTION_MOVE:
if(父类容器需要) {
intercepted = true;
} else {
intercepted = false;
}
break;
case MotionEvent.ACTION_UP:
intercepted = false;
break;
return intercepted;

注:ACTION_DOWN事件父类容器就必须返回false,因为如果父类容器拦截了的话,后面的Move等所有事件都会直接由父类容器处理,就无法传给子元素了。UP事件也要返回false,因为它本身来说没有太多的意义,但是对于子元素就不同了,如果拦截了,那么子元素的onClick事件就无法触发。

内部拦截法 
这种方法指的是父容器不拦截任何时间,所有的事件都传递给子元素,如果子元素需要此事件就直接消耗掉,否则就交给父容器进行处理。它需要配合requestDisallowInterceptTouchEvent方法才能正常工作。我们需要重写子元素的dispatch方法。

    case MotionEvent.ACTION_DOWN:
parent.requestDisallowInterceptTouchEvent(true);
break;
MotionEvent.ACTION_MOVE:
if(父容器需要此类点击事件) {
parent.requestDisallowInterceptTouchEvent(false);
}
break;
return super.dispatchTouchEvent(event);

这种方法的话父类容器需要默认拦截除了ACTION_DOWN以外的其他时间,这样当子元素调用request方法的时候父元素才能继续拦截所需的事件。

其他的 
      如果觉得上面两个方式太复杂,看晕了,其实也可以自己根据项目的实际需要来指定自己的策略实现。例如根据你手指按的点的位置来判断你当前触碰的是哪个控件,以此来猜测用户是否是要对这个控件进行操作。如果点击的是空白的地方,就操作外部控件即可。

,具体可参考ViewPager中的滑动冲突

Android中点击事件的处理解析及常见问题的更多相关文章

  1. Android中点击事件的四种写法详解

    Android中点击事件的四种写法 使用内部类实现点击事件 使用匿名内部类实现点击事件 让MainActivity实现View.OnClickListener接口 通过布局文件中控件的属性 第一种方法 ...

  2. Android中点击事件的实现方式

    在之前博文中多次使用了点击事件的处理实现,有朋友就问了,发现了很多按钮的点击实现,但有很多博文中使用的实现方式有都不一样,到底是怎么回事.今天我们就汇总一下点击事件的实现方式. 点击事件的实现大致分为 ...

  3. android中点击事件的4种写法

    android中获取到一些控件(比如说按钮)时,一般会为其添加点击事件,android中的点击事件一共有4中写法. 假设在布局文件中声明如下 ....... <Button android:la ...

  4. JS中点击事件冒泡阻止

    JS中点击事件冒泡阻止 解析: 一个div层'out',内含有一个div层'in'.如下: 两个层都绑定了点击事件,但是点击in层的时候,点击事件会出现冒泡现象,同时也会触发out层的点击事件. 但是 ...

  5. Android中点击隐藏软键盘最佳方法——Android开发之路4

    Android中点击隐藏软键盘最佳方法 实现功能:点击EditText,软键盘出现并且不会隐藏,点击或者触摸EditText以外的其他任何区域,软键盘被隐藏: 1.重写dispatchTouchEve ...

  6. Android点击事件(click button)的四种写法

    在学习android开发和测试的时候发现不同的人对于click事件的写法是不一样的,上网查了一下,发现有四种写法,于是想比较一下四种方法的不同 第一种方法:匿名内部类 代码: package com. ...

  7. Android点击事件

    Android点击事件 备注 全局实现View.OnClickListener 或许需要将MainActivity设置为public 注册事件 btn_login.setOnClickListener ...

  8. js for循环中点击事件中无法获取每一个i值的问题

    好像是第二次遇到这个问题,必须要总结一下!! <!DOCTYPE html> <html> <head> <meta charset="utf-8& ...

  9. android点击事件的四种方式

    android点击事件的四种方式 第一种方式:创建内部类实现点击事件 代码如下: package com.example.dail; import android.text.TextUtils; im ...

随机推荐

  1. 树(弱化版)(lca)

    3306: 树 时间限制: 10 Sec  内存限制: 256 MB 题目描述 给定一棵大小为 n 的有根点权树,支持以下操作:  • 换根  • 修改点权      • 查询子树最小值 输入 第一行 ...

  2. Network | parity bit

    奇偶校验位是一个表示给定位数的二进制数中1的个数是奇数还是偶数的二进制数.奇偶校验位是最简单的错误检测码. A parity bit, or check bit is a bit added to t ...

  3. loj #110. 乘法逆元

    #110. 乘法逆元 内存限制:256 MiB时间限制:1000 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: 匿名 提交提交记录统计讨论测试数据   题目描述 这是一道模板题. 给定 ...

  4. MongoDb 出现配置服务不同步的处理

    主要片方法就是用正常的配置文件的数据覆盖有问题的就行. 引用: http://dba.stackexchange.com/questions/48232/mongodb-config-servers- ...

  5. 【转载】GitHub中国区前100名到底是什么样的人

    转载了这篇文章: http://www.jianshu.com/p/d29cba7934c9 这篇文章真是太牛了!转载过来涨涨见识,同时好好励志一把.还有,ruanyifeng怎么长那样... 哈 另 ...

  6. Hadoop 2.2.0集群搭建

    一.环境说明 1.虚拟机平台:VMware10 2.Linux版本号:ubuntu-12.04.3-desktop-i386 3.JDK:jdk1.7.0_51 4.Hadoop版本号:2.2.0 5 ...

  7. SWF代码分析与破解之路 (YueTai VIP视频信息获取工具) Socket续篇

    引言 上一篇 <Socket与站点保密应用 (隐藏链接的视频下载)>大大咧咧地从 WEB 讲 Socket.再到 TCP/IP 等协议,又再讲到 Wireshark 怎样抓IP包分析.最还 ...

  8. C#报错"线程间操作无效: 从不是创建控件“XXX”的线程访问它"--解决示例

    C# Winform程序中,使用线程对界面进行更新需要特殊处理,否则会出现异常“线程间操作无效: 从不是创建控件“taskView”的线程访问它.” 在网文“http://www.cnblogs.co ...

  9. Cocos2d-x初识

    cocos2d-x引擎是什么 在学习游戏的时候就有意的搜索这方面的知识,知道游戏须要游戏引擎,引擎听着非常厉害,只是就是一个游戏框架. 或许某一个游戏框架火起来了,就非常流行了,只是我觉得不论什么游戏 ...

  10. 安装odoo 9实录

    安装Ubuntu,省略 下载 odoo源码 使用 git 下载源码 mkdir /opt/openerp/server cd /opt/openerp/server git clone https:/ ...