Android View的事件分发机制

何为事件

事件,在Android中的载体是MotionEvent。Android中的触摸事件被封装为MotionEvent,包括 事件发生 的位置、时间、历史记录以及第几个手指(多指触摸)等。

MotionEvent可以分为几类:ACTION_DOWN, ACTION_UP, ACTION_MOVE, ACTION_POINTER_DOWN, ACTION_POINTER_UP, ACTION_CANCEL,每个事件都是以 ACTION_DOWN 开始 ACTION_UP 结束。

事件的分发

从两个角度来看Android中View的事件分发:
1.事件的传递
事件的传递遵循的原则是从父View到子View,或者说从最底层View到最上层View(人眼看到的Android系统或应用界面为最上层View)。在屏幕探测到来自外界的触摸事件时,Android系统会依据一定的算法确定事件发生的具体位置,从而确定可能接收到触摸事件的View。

然后,Android按照这样的规则来传递事件:从Activity.dispatchTouchEvent()开始,按照从父View到子View的顺序,只要传递路径上的任意一个ViewGroup(特殊的View)没有使用onInterceptTouchEvent()方法拦截事件(通过返回true来拦截事件),事件就会一直传递直到最上层的子View。这是事件的传递过程,Android严格的按照这一顺序来将事件在View之间传递。

2.事件的处理
我们假设事件在传递的过程中没有被任何一个ViewGroup拦截,那么现在事件就传递到了最上层的View,接下来就需要确定事件该如何处理,即谁会消费这一事件。

事件的消费涉及到View的两个成员,onTouchListener()回调和onTouchEvent()方法。根据Android官方的解释,如果设置了onTouchListener()回调,那么onTouchListener()回调会在 onTouchEvent()之前被调用。View可以通过在这两个方法之中的任意一个返回true来告知Android系统自己消费了这个事件。反之,如果View返回了false,那么Android系统将会按照传递事件的反向顺序依次调用父View的onTouchListener()回调和/或onTouchEvent()方法直到传递路径上的某个View的某个成员返回true告知Android系统自己消费了这一事件。如果事件反向处理的过程中没有任何View消费此事件,那么事件最终会回到Activity的onTouchEvent()方法中。这是事件的处理过程。

在前文中曾提到过,一个事件从MotionEvent的ACTION_DOWN开始直到ACTION_UP结束。对于事件的分发来说,如果某一个View消费了一个事件的ACTION_DOWN操作,那么接下来的这个事件的一系列操作都会被此View消费(即此View的父类View都不会拦截和消费这个事件的剩余操作)。对于同一个事件来说,一个View可以通过显式的调用requestDisallowInterceptTouchEvent()方法来告知其所有父View不要拦截某一事件。

最后

用个形象的例子来描述事件的分发机制,部门经理--项目经理--干活的职员。现在有一个任务要做,这个任务会按照部门经理、项目经理、干活的职员的顺序传递。如果任务太简单,部门经理或者项目经理可能就自己解决了(拦截事件),这就是事件分发过程中的拦截操作。如果任务传递过程中部门经理和项目经理都没有处理,最后就到干活的职员头上。到干活的职员这里了,她/他觉得不爽快,直接辞职,就没人干活了,这里就等于直接返回了true。如果干活的职员做完了任务,她/他需要向上级报告,等于返回false。项目经理如果看到你完成的结果后觉得做得太差就没向部门经理上报而是自己处理了(消费事件);相反,如果项目经理觉得干活的职员处理的不错需要向部门经理汇报,那就会返回false往上层处理。直到最后部门经理决定如何处理这一事件,这里就等于Activity的onTouchEvent()方法。

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