Android:ViewGroup事件分发机制

关于ViewGroup事件分发机制的文章已经有很多了,推荐郭霖和鸿洋的两篇文章, 结合他们写的,自己简单总结一下,可能只适用个人。

流程

在上一篇文章中讲到,当你操作一个控件时,不管是按下、移动、抬起,,在事件中途未被消费的情况下系统会按照View.dispatchTouchEvent -> OnTouchListener.onTouch -> View.onTouchEvent分发下去。事实上,事件最先分发到的是ViewGroup的dispatchTouchEvent、然后分发到onInterceptTouchEvent方法,而第二个方法顾名思义就是用来拦截消费事件的。代码如下,默认就是不拦截。

(MotionEvent ev) {return false; }

接下来看一下ViewGroup.dispatchTouchEvent方法,源码比较长为了不占篇幅,可以直接在上面的文章看。观察源码可以发现,当按下控件时事件会分发到onInterceptTouchEvent方法中,而默认这个方法是返回false,然后系统通过坐标的计算得出当前按的控件是否是ViewGroup里面的子View,如果是,将事件分发给这个子View,也就是按照View.dispatchTouchEvent -> OnTouchListener.onTouch -> View.onTouchEvent**,并且将这个子View赋给target记录下来,方便后面控件移动、抬起操作的识别。如果不是,则会有如下代码

if (target == null) {ev.setLocation(xf, yf);if ((mPrivateFlags & CANCEL_NEXT_UP_EVENT) != 0) {ev.setAction(MotionEvent.ACTION_CANCEL);mPrivateFlags &= ~CANCEL_NEXT_UP_EVENT;}return super.dispatchTouchEvent(ev);}

可以看到如果点击的不是子View,则会把事件分发到super.dispatchTouchEvent方法,而ViewGroup的父类正是View,所以可以这么理解,点击一个控件时,先在ViewGruop.dispatchTouchEvent里面判断点击的是不是子View,是则按照View的事件分发机制分发下去,否则把ViewGroup本身作为一个View,按照View的事件分发机制分发下去。而常见的ViewGroup无非就是一些布局还有AdapterView等。

小结如果ViewGroup可以找到子View,就将事件分发给子View,否则自己作为一个View分发事件。通过重写ViewGroup.onInterceptTouchEvent方法可以实现对不同动作的事件的拦截,由ViewGroup自身处理事件。

分析两篇文章,我们一般都不需要重写ViewGroup和View的dispatchTouchEvent方法和View.onTouchEvent方法,程序员需要关心的是ViewGroup.onInterceptTouchEvent和onTouch,前者是实现ViewGroup对子View事件的拦截,后者是实现View分发流程时onTouch方法对onTouchEvent方法的拦截,而onTouchEvent则是实现判断onLongClick和onClick等动作的逻辑的。 ViewGroup.onInterceptTouchEvent默认返回false,则点击到子View时会把事件分发给子View,onTouch返回false或者不存在OnTouchListener时,则会把事件分发到onTouchEvent,onLongClick返回false或者不存在OnLongClickListener时,事件才有可能传递给onClick方法

一个今天胜过两个明天

Android:ViewGroup事件分发机制

相关文章:

你感兴趣的文章:

标签云: