Android View 事件分发

关于事件分发,关键是要理清楚三个方法的关系,
dispatchTouchEvent
onInterceptTouchEvent
onTouchEvent

如果没有任何View拦截处理事件,并且每个View也不处理这个事件,那么这个事件会按照如下方式流转:

事件会以父元素到子元素的顺序去传递事件,
事件会以子元素到父元素的顺序去消费事件。
是一个U型结构。

其中只有ViewGroup中有onInterceptTouchEvent,用来判断是否拦截事件。
而dispatchTouchEvent方法有点特殊,这个方法在View中和ViewGroup中实现是不一样的。ViewGroup继承自View,并且复写了这个dispatchTouchEvent方法。
View 的dispatchTouchEvent的主要功能是负责时间的消费,即调用onTouchEvent。
VIewGroup 的dispatchTouchEvent主要功能是负责事件的分发。但是当发现这个事件需要自己处理的时候,就回调用super.dispatchTouchEvent()。这个super的方法就是View中的方法实现,即开始调用onTouchEvent消费这个事件。

对于各个方法的返回值的不同,事件的流向可以参考下面这个图


一个事件流包括一个DOWN、UP和 n 个MOVE三种子事件。
这三个事件中,最重要的事件是** DOWN **事件。
当一个View处理了DOWN事件以后,系统会认为他要处理这整个事件,就回将后续的MOVE和UP事件都交由它处理。
所以DOWN事件是一个很特别的事件,。

情况一:

如果没有任何View处理这个事件,那么这个事件会传递到Activity的onTouchEvent中。
所有的事件流转过程中的方法,只会受到一个子事件:DOWN。
其他子事件在流转过程中都不会受到。
因为没有View处理DOWN事件,系统认为没有要处理这个事件的控件,后续的所有的事件都不会在流程中传递。

情况二:

如果ViewGroup处理了DOWN事件。
那么事件的流转就不会在到View,直接交给了ViewGroup去处理了,直接调用ViewGroup的onTouchEvent事件。


情况三:

View处理了DOWN事件,那么这个事件系统会交由这个View进行处理。
直接调用这个View的onTouchEvent事件去处理。
但是这个时候,ViewGroup是可以拦截MOVE和UP事件的。
如果ViewGroup选择性拦截了MOVE和UP,那么这个View就仅仅只收到GroupView没有拦截的事件,被拦截掉的MOVE和UP都会交由ViewGroup的onTouchEvent去处理。
这也是处理滑动冲突的基本思路,就是按照条件过滤MOVE事件,达到解决冲突的目的。

这里注意,当ViewGroup拦截了MOVE和UP事件后,View的ACTION_CANCEL事件会被调用。


点击事件的处理:

默认情况下,View的onTouchEvent是不处理事件的,即返回false,但是当这个View的clickable或者longClickable为true时,这个View就回默认返回true,即默认处理touch事件。

事件优先级

onTouchEvent < OnTouchListener

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容