View触摸反馈与事件分发原理 View的触摸反馈用于定义View对各类点击事件的响应方式。是进行自定义View的核心环节。本文详细介绍事件达到View后的事件拦截模型、分发流程,以及View原生事件处理方式。帮助大家更好的理解和掌握Android事件的原理和进行自定义view实践。1、事件分发模型我们以一个简单的View结构:一个ViewGroup和两个有交叠的子View,来看一下事件分发的典型模型。用户点击屏幕后,事件会被InputManager捕捉到,然后传递给Window,再通过Window传递到DecorView。然后再一级一级,从上到下传下来。这个过程不在这里详细介绍。读者可以从我的另一篇文章“从子线程更新UI异常问题看View加载绘制流程”了解一下view和window的关系。这里我们直接从事件到达View开始讲起。事件到达View首先是会到达View树上最顶层的布局,如上面图的“父View”,它是一个容器。先调用父View的dispatchTouchEvent方法,然后onInterceptTouchEvent()方法判断是否进行拦截。如果不拦截,则走图上黑色箭头的路线。事件首先到达点击范围内屏幕最上层的子View,如果子View将事件消费,则事件到此结束,此次事件将由该View处理;如果子View不消费,则传递到它下层的子View,继续做同样的判断,如果所有子view都不消费。最后由父View处理。如果开始时父view的onInterceptTouchEvent()方法拦截事件,则事件不会再向子View分发,直接由父View处理。如上图的红色箭头流程。以上就是典型的事件分发的模型,如果多层父View和多个子View,只要递归的看就可以了。如果涉及到事件的拦截,要复杂一些,我们后面再看。2、事件序列Android的触摸事件,主要有ACTION_DOWN(手指按下)、ACTION_MOVE (手指移动)、ACTION_UP(手指抬起)。其他还有ACTION_POINT_DOWN (非第一根手指按下)、ACTION_POINT_UP(非第一根手指抬起)、ACTION_CANCEL(事件取消)等。实际上事件的产生都是伴随着一个完整的过程,是一个事件序列。它是从DOWN(触摸)事件开始,中间经历一系列的MOVE(滑动)事件,最后以UP或CANCEL事件结束(手指抬起)。我们在讨论事件分发、拦截、处理时,考虑的都是一个完整的事件序列。3、事件拦截与分发我们已经知道事件分发的基本模型。本章节将详细看一下事件分发与拦截流程。主要是在ViewGroup的dispatchTouchEvent()方法中进行。接下来我们详细分析该源码。请读者在阅读时,时刻回忆上一章节的事件分发的模型。ACTION_DOWN除了表示一个手指按下事件,还表示这是一个新的事件序列的开始。因此先对之前的标志、状态进行清空初始化。3.1拦截的判断intercepted就是是否要进行拦截的判断,可以理解为接下来是否要进行事件分发。事件分发就是通过一定方法,在view树中找到最合适处理该事件的控件的过程,详细内容在“事件分发”中进行介绍。intercepted为true,表示进行拦截,不走分发流程,直接走事件处理。如果intercepted为false,表示需要进行事件分发,分发完成后再进行事件处理。“mFirstTouchTarget != null”, 表示此时有子view在处理此次事件序列。如果是事件序列开始或者有子view在处理事件时,进行进一步判断。否则,设置intercepted为true,走事件处理流程。接下来判断,如果子view设置了不允许拦截,则intercepted为false,进行事件分发。如果子view未设置,则通过onInterceptTouchEvent方法判断父view是否拦截,这种方式叫做外部拦截。“FLAG