Android中事件传递机制的总结
事件传递虽然算不上某个单独的知识点,但是在实际项目开发中肯定会碰到,如果不明白其中的原理,那在设计各种滑动效果时就会感到很困惑。
关于事件的传递,我们可能会有以下疑问:
事件是如何传递的
事件是如何处理的
自定义view的时候,事件也冲突了怎么解决
带着这三个疑问,我们来总结一下事件传递机制是怎么回事。
一、事件分发的原理:
1、事件是如何传递的(捕获阶段,由外向内层层捕获):
(1)首先由Activity分发,分发给根View,也就是DecorView(DecorView为整个Window界面的最顶层View)
(2)然后由根View分发到子的View
如下图所示:
再来看下面这张图:(这张图是整个事件传递机制的核心)
上图显示:
在ViewGroup中可以通过onInterceptTouchEvent方法对事件传递进行拦截。onInterceptTouchEvent方法:
返回true代表不允许事件继续向子View传递,将会触发当前View的onTouchEvent(),进行事件的消费;
返回false代表不对事件进行拦截,事件可以传递给孩子
默认返回false
2、事件是如何处理的(冒泡阶段,由内向外层层传递):
再来看下面这张图:
上图显示:子View中如果将传递的事件消费掉,父类的ViewGroup中将无法接收到任何事件。
二、onTouch和onClick事件同时发生的问题:
首先这里要解释一下各种概念,避免混淆。
1、各种概念:
事件:
混合体(可能是点击事件也可能是触摸事件)。
触摸事件:
按下、滑动和离开
点击事件:
按下、停留一会儿和离开
触摸onTouch事件和点击onClick事件有什么关系?
(1)执行先后不一样。触摸事件先执行
(2)触摸事件返回值影响点击事件(前者影响后者,而后者不影响前者)
2、onTouch和onClick事件同时执行:
如果按钮的onTouch和onClick方法同时执行,会有什么效果呢?我们通过代码来看一下:
1 import android.app.Activity; 2 import android.os.Bundle; 3 import android.util.Log; 4 import android.view.MotionEvent; 5 import android.view.View; 6 import android.widget.Button; 7 8 public class MainActivity extends Activity { 9 10 private static final String TAG = "MainActivity"; 11 private Button btn; 12 13 @Override 14 protected void onCreate(Bundle savedInstanceState) { 15 super.onCreate(savedInstanceState); 16 setContentView(R.layout.activity_main); 17 btn = (Button) findViewById(R.id.btn); 18 19 //按钮的touch触摸事件 20 btn.setOnTouchListener(new View.OnTouchListener() { 21 @Override 22 public boolean onTouch(View v, MotionEvent event) { 23 switch (event.getAction()) { 24 case MotionEvent.ACTION_DOWN: //按下的动作 25 Log.d(TAG, "btn is MotionEvent.ACTION_DOWN"); 26 break; 27 case MotionEvent.ACTION_MOVE: //滑动的动作 28 Log.d(TAG, "btn is MotionEvent.ACTION_MOVE"); 29 break; 30 case MotionEvent.ACTION_UP: //离开的动作 31 Log.d(TAG, "btn is MotionEvent.ACTION_UP"); 32 break; 33 } 34 35 return false; //默认的返回值 36 } 37 }); 38 39 //按钮的点击事件 40 btn.setOnClickListener(new View.OnClickListener() { 41 @Override 42 public void onClick(View v) { 43 Log.d(TAG, "btn is click"); 44 } 45 }); 46 } 47 48 }
上方代码中,按钮btn既包含了onTouch事件,也包含了onClick事件,现在运行程序,点击按钮,后台打印的日志如下:

通过上方日志我们可以看到,onTouch事件是比onClick事件先执行的。
备注:这里提示一下,如果我们仅仅只是用手指点击按钮,然后马上松开,onTouch事件中只会执行ACTION_DOWN和ACTION_UP动作;如果用手机点击按钮,并且手指还在按钮上滑动了一会儿,那么滑动的过程中,ACTION_MOVE动作就会不停的执行。现在我们应该能明白这三个动作的含义了吧?
3、只执行onTouch事件,不执行onClick事件:
如果按钮的onTouch和onClick方法同时执行,在有些情况下不太满足产品的需求。那如果只想执行onTouch事件,不执行onClick事件,该怎么做呢?很简单,只需要在上方代码中,将第39行的代码改为return true,就行了,即:将onTouch方法的返回值改为true,就会只执行onTouch事件,不执行onClick事件。改完代码之后,后台的运行效果如下:

为什么这样改代码就可以了呢?这就需要从源码的角度来理解了。
button按钮中没有dispatchTouchEvent方法,需要去它的父类View.java中去找dispatchTouchEvent方法。源码如下所示:



三、onClick和onLongClick事件能同时发生:
我们通过代码来演示一下。
1、onTouch事件、onLongClick事件、onClick事件默认是同时执行:(执行的先后顺序:onTouch > onLongClick > onClick)
通过查看源码我们得知,当onTouch事件中的ACTION_DOWN动作执行180ms之后,就会执行onLongClick事件。
那我们现在知道了,如果在一个按钮上按下的时间过长,onLongClick事件会比onClick事件先执行。
2、只执行onTouch事件和onLongClick事件,不执行onClick事件:
为了实现这种逻辑,也很简单,只需要将上方的第50行代码改为return true就行了,即:将onLongClick方法的返回值改为true,就不会执行onClick事件了。为什么这样改代码就可以了呢?这就需要从源码的角度来理解了。在View.java中的dispatchTouchEvent方法里,ACTION_UP动作里面对onLongTouch事件进行了处理,具体源码就不展示出来了,这个有点复杂。
四、事件传递机制调用顺序:
ViewGroup的事件传递方法:
- dispatchTouchEvent
- onInterceptTouchEvent
- onTouchEvent
View的事件传递方法:
- View的dispatchTouchEvent
- View的onTouchEvent
注意,只有父的ViewGroup容器才有onInterceptTouchEvent方法。这也很好理解,最小的那个子的view没必要再拦截了,因为无法继续向下传递事件,是否拦截已经没有意义了。
相关信息
- Android中的事件分机制
- IO中手机旋转事件的传递
- Android中事件传递机制的总结
- Android中事件传递机制的总结
- spring 事务传播机制总结
- android 事件分发机制
- Javascript事件总结
- javascript事件机制
- nodejs 事件机制
- Java中参数传递时值传递的机制分析
- Android 触摸事件传递机制
- Android 触摸事件传递机制
- Android触摸事件传递机制
- Spring事务传播机制
- StartActivityForRequest的传递机制,从下一个活动向上一个活动传递数据
- Android学习总结——Activity之间传递参数
- Android - 事件模型-事件传递,处理机制
- Android查缺补漏(View篇)--事件分发机制
- Spring之事件机制详解
- Android触摸事件传递机制
- Android 事件传递机制
- Android 高级UI4 事件传递机制
- 初识Android触摸事件传递机制
- Android事件处理机制
- Android事件分派机制
- JavaScript事件机制——细思极恐
- JQuery 总结(3) jQuery 各种事件
- SSIS 事件的向上传递
- Android TouchEvent事件传递机制
- Android TouchEvent事件传递机制
- Android touch 事件传递机制
- onTouch事件传递机制
- Android消息传递之Handler消息机制
- Qt事件处理机制
- JavaScript系列----事件机制
- C#中的引用传递和值传递。
- Android 事件传播机制
- Android事件分发机制完全解析,带你从源码的角度彻底理解
- Spring事务传播行为详解
- JQuery绑定事件 时如何传递参数
- android控件的事件传播机制
- android控件的事件传播机制
- android控件的事件传播机制
- Qt消息机制和事件(一)
- 事件传递机制
- 事件传递机制
- Android事件分发机制源码分析
- JAVA参数传值机制中值传递和引用传递
- 深入理解JAVA事件机制
- WPF中的事件及冒泡事件和隧道事件(预览事件)的区别
热门资讯
推荐资讯
最新资讯
- 每个程序员必学的10个Git命令
- 学习 WCF (4)--学会使用配置文件 无论是Web应用程序还是Win应用程序,我们都会经常用到配置文件。WCF作为分布式开发的基础框架,在定义服务以及定义消费服务的客户端时,都使用了配置文件的方法...
- WCF 新手教程二
- Hibernate为什么如此成功?
- Dubbo线程模型
- 概述异步编程模型
- BM00002——|Javase|MS-DOS(Microsoft Disk Operating|
- MS-DOS 6.22 +Vim+masm 汇编环境
- 批量下载 Windows 零散系统更新的得力工具 -Windows Updates Downloader
- NO.A.0002——day01——MS-DOS(Microsoft Disk Operating System)
- ubuntu 中文拼音输入法安装
- 在ubuntu10.10下安装Google谷歌拼音输入法
- [转]ubuntu14.04安装好用的google拼音输入法
- (转)[GIT]Fatal: cannot do a partial commit during a merge
- libevent(十四)http client 请求 (GET、POST)
- Mysql 保存float数组的一种方式
- 极简主义
- JVM调优
- JVM调优-GC基本原理和调优关键分析
- 通过日志分析,实现 Kubernetes Helm Release 的自动回滚
评论