Android Touch分发事件机制详解

**********如果你理解起来比较困难,那你可以看看我的东西,一行一行读下去,至少理解肯定没问题*****

这里主要是针对面试的速成知识点:

原文:https://www.jianshu.com/p/38015afcdb58这里写的特别棒

http://www.cnblogs.com/sunzn/archive/2013/05/10/3064129.html

事件分发主要是指对Touch事件的处理,何为Touch事件?

就是我们常说的点击,触摸事件

Touch事件的相关细节被封装成了一个事件对象:

(发生触摸的位置、时间等)MotionEvent对象

概念**********************************************************************************************

###一个定义:那么Touch事件的分发过程,就是指MotionEvent对象的传递,最终由谁来处理的过程;

或者说事件(MotionEvent)传递到某个具体的View & 处理的整个过程

事件传递的过程 = 分发过程

###四种类型:Touch事件类型:

MotionEvent.ACTION_DOWN按下View(所有事件的开始)

MotionEvent.ACTION_UP抬起View(与DOWN对应)

MotionEvent.ACTION_MOVE滑动View

MotionEvent.ACTION_CANCEL结束事件(非人为原因)

一般手机触摸屏幕,再离开屏幕的过程,会出发一系列的Touch事件

一般情况下,事件列都是以DOWN事件开始、UP事件结束,中间有无数的MOVE事件

当一个事件(MotionEvent )产生后,系统需把这个事件传递给一个具体的 View去处理

原理和过程分析:****************************************************************************

###主要三个对象:Activity,ViewGroup,View

事件传递是在Activity,ViewGroup,View之间传递

事件传递的顺序:Activity -> ViewGroup -> View

即:1个点击事件发生后,事件先传到Activity、再传到ViewGroup、最终再传到 View

###主要三个方法:

dispatchTouchEvent() 、onInterceptTouchEvent()和onTouchEvent()

三个对象,每个对象里都有dispatchTouchEvent()和onTouchEvent()方法

ViewGroup里多了一个onInterceptTouchEvent()

**********把以下的分析明白就OK了

这里直接教你面试的时候怎么说:

(1)Activity对点击事件的分发机制

首先会先回掉Activity的dispatchTouchEvent方法,最终会交给ViewGroup的

dispatchTouchEvent()处理。

过程:————————————————————————————————————---------------------


getWindow获取window类的对象,指向唯一的实现类Phonewindow对象,然后再调用他

的superDispatchTouchEvent(ev)方法:

里面调用到:

mDecor.superDispatchTouchEvent(event);

mDecor是(DecorView)的实例对象

a. DecorView类是PhoneWindow类的一个内部类

 b. DecorView继承自FrameLayout,是所有界面的父类

 c. FrameLayout是ViewGroup的子类,故DecorView的间接父类 = ViewGroup

// 调用父类的方法 = ViewGroup的dispatchTouchEvent()// 即 将事件传递到ViewGroup去处理

—————————————————————————————————————————————

ViewGroup的dispatchTouchEvent如果返回true,则不会再执行Activty的OnTouchEvent()方法;

ViewGroup的dispatchTouchEvent如果返回false,则继续执行Activty的OnTouchEvent()方法;

OnTouchEvent这个方法是在当Activty上面所有的View都没有接收处理这个事件的时候

而且要求Activity的dispatchTouchEvent返回false super.OnTouchEvent,才会触发

第一种情况:

比如说你的Activity上什么都没有,但是你触摸了屏幕就一定会触发dispatchTouchEvent,如果没有View消费掉事件,那么会继续触发OnTouchEvent()事件

第二种情况:

如果Activty上有一个按钮,给按钮添加一个点击事件,那么这个按钮被点击时会触发Activity的dispatchTouchEvent方法,但是这个事件被Activity中的Button消费掉 了,那么Activity的OnTouchEvent就不会再继续执行了

注意:

如果Activty的dispatchTouchEvent直接返回false或者True,那么OnTouchEvent()和按钮都不会接收到这个事件了

(2)ViewGroup对点击事件的分发机制

再Activity分发事件的里面可以发现ViewGroup的事件分发也是从dispatchTouchEvent开始的,

在ViewGroup的dispatchTouchEvent,ViewGroup每次事件分发时,都需调用onInterceptTouchEvent()询问是否拦截事件,

ViewGroup.onInterceptTouchEvent()

  * 作用:是否拦截事件

  * 说明:

  *    a. 返回true = 拦截,即事件停止往下传递(需手动设置,即复写onInterceptTouchEvent(),从而让其返回true)

  *    b. 返回false = 不拦截(默认)

  */publicbooleanonInterceptTouchEvent(MotionEvent ev){returnfalse;  }

如果没有拦截,通过for循环,遍历了当前ViewGroup下的所有子View

/ 判断当前遍历的View是不是正在点击的View,

从而找到当前被点击的View// 若是,则进入条件判断内部

// 条件判断的内部调用了该View的dispatchTouchEvent()// 即 实现了点击事件从ViewGroup到子View的传递

// 调用子View的dispatchTouchEvent后是有返回值的// 若该控件可点击,那么点击时,dispatchTouchEvent的返回值必定是true,因此会导致条件判断成立// 于是给ViewGroup的dispatchTouchEvent()直接返回了true,即直接跳出// 即把ViewGroup的点击事件拦截掉

如果onInterceptTouchEvent是拦截的状态

那么返回true = 拦截,即事件停止往下传递,由ViewGroup自己的函数OnTouchEvent等等来处理这个事件

(3)View对点击事件的分发机制



总结:

dispatchTouchEvent 和OnTouchEvent的结果一致,返回true代表事件被消费了

有一层的OnTouchEvent返回了true


被消费一定是在OnTouchEvent中消费,就是在哪一层消费的问题

默认是dispatchTouchEvent的调用会一层一层的向下传递,

OnTouchEvent会一层一层向上传递


就是这个意思:

Activity的dispatchTouchEvent 会调用到ViewGroup的dispatchTouchEvent,

ViewGroup的dispatchTouchEvent会调用到View的dispatchTouchEvent对象

如果有一层返回了true都代表事件被消费了


如果都返回false,那么就回掉Activity的OnTouchEvent方法消费

如果ViewGroup层的拦截器返回true代表拦截,那么就是ViewGroup这一层的OnTouchEvent消费事件

如过默认条件下没有拦截,由view处理,就回掉view的OnTouchEvent消费


如果没有传递到view层,那么onclick就不会被触发了

你可能感兴趣的:(Android Touch分发事件机制详解)