Android事件分发之View分发事件
前言
在我们平时开发中,对于自定义View,我们一般都是继承至已经实现的View或者ViewGroup,对于直接继承至View的情况还是比较少的,刚好最近做了一个项目,其中就有一个自定义View继承至View,所以这方面知识需要加深一下。
事件分发到View也是分发到底了,这部分也比较简单。
View的dispatchTouchEvent方法
直接来看一下View的dispatchTouchEvent关键代码:
//View的dispatchTouchEvent方法 关键代码
ListenerInfo li = mListenerInfo;
//先判断是否设置TouchListener
if (li != null && li.mOnTouchListener != null
&& (mViewFlags & ENABLED_MASK) == ENABLED
&& li.mOnTouchListener.onTouch(this, event)) {
result = true;
}
//再判断onTouchEvent返回值
if (!result && onTouchEvent(event)) {
result = true;
}
这里基本就是全部的代码了,其中dispatchTouchEvent的返回值就是代表是否消费掉点击事件,这个返回值直接影响着其上层View是否需要再调用自己的处理逻辑(对于ViewGroup来说是调用super.dispatchTouchEvent,对于Activity来说是调用onTouchEvent)。
3个判断条件
这里第一个if有3个判断条件,当全是ture则不会再执行onTouchEvent方法,这里要记住。
-
mOnTouchListener != null ,即这个View设置了OnTouchListener。
-
(mViewFlags & ENABLED_MASK) == ENABLED,这个View是可点击的,对于View来说,默认是可点击的。
-
mOnTouchListener.onTouch返回值为true。
这里3个条件还是蛮苛刻的,原因很简单,一般我们很少自己给View设置TouchListener监听,即使设置了,也必须在onTouch返回true才可以,至于为什么这样,暂时还有深究过。
当3个条件有一个不为空,则执行onTouchEvent方法。
View的onTouchEvent方法
对于onTouchEvent方法我们在自定义View时使用的较多,这个是在dispatchTouchEvent方法内部调用,这里其实就是对MotionEvent事件进行处理,注意2点即可,第一个是在处理UP事件时,是否需要回调ClickListener回调,另一个对于各种复杂的手势以及操作可以通过手势识别类来辅助完成。
整体流程图
View的分发比较简单,主要就是会在2个地方使用,一个是事件已经分发到最上层View了,这时由这个View而不是ViewGroup来进行调用dispatchTouchEvent和onTouchEvent来完成逻辑;一个是ViewGroup在分发事件给子View时,事件没有消耗,即子View的dispatchTouchEvent返回false,或者点击的是ViewGroup的空白地方,这是也会调用ViewGroup的父类即View的事件分发。
这里从其他博客拷贝一张觉得很不错的图,来表示一下流程:
总结
Android事件分发作为自定义View的基础是必须要掌握的,其中设计的思路还是非常巧妙的,如果不仔细理解清楚,在处理事件拦截时和其他View配合将会有点疑惑。
这里重点也是集中在责任链思想、ViewGroup分发和拦截事件、View的监听器优先级顺序等,后面会细说举例这些事件分发原理的重要性。