View事件消费
View事件是如何消费的
我们知道View处理事件流程是先 dispatchTouchEvent 然后 onTouchEvent 所以先从dispatchTouchEvent 方法开始分析
public boolean dispatchTouchEvent(MotionEvent event) {
// 这里开始对事件进行处理
if (onFilterTouchEventForSecurity(event)) {
if ((mViewFlags & ENABLED_MASK) == ENABLED && handleScrollBarDragging(event)) {
result = true;
}
//
ListenerInfo li = mListenerInfo;
// 判断 mOnTouchListener 是否为空
// 不为空调用mOnTouchListener的onTouch
// 而mOnTouchListener 就是我们View 自己设置的setOnTouchListener()
//li.mOnTouchListener.onTouch(this, event) 这个如果我们返回true
//那么就下面的 if (!result && onTouchEvent(event))不会执行了
if (li != null && li.mOnTouchListener != null
&& (mViewFlags & ENABLED_MASK) == ENABLED
&& li.mOnTouchListener.onTouch(this, event)) {
result = true;
}
if (!result && onTouchEvent(event)) {
result = true;
}
}
return result;
}
上面的逻辑 我们可以看出 只要View.setOnTouchListener() 返回true 影响了result onTouchEvent就不会执行,如果不返回true 接下来分析一下onTouchEvent 做了什么
源码如下
public boolean onTouchEvent(MotionEvent event) {
if (clickable || (viewFlags & TOOLTIP) == TOOLTIP) {
switch (action) {
case MotionEvent.ACTION_UP:
if (!post(mPerformClick)) {
// 单手指离开的时候会调用点击事件 继续看该方法
performClickInternal();
}
break;
}
}
// 这里会调用到performClick 继续看下一步
private boolean performClickInternal() {
notifyAutofillManagerOnClick();
return performClick();
}
public boolean performClick() {
final boolean result;
final ListenerInfo li = mListenerInfo;
//mOnClickListener 其实就是对View点击的监听
//也就是我们说的setOnClickListener
// 所以到这里基本就可以完全明白 事件是什么处理的了
if (li != null && li.mOnClickListener != null) {
playSoundEffect(SoundEffectConstants.CLICK);
li.mOnClickListener.onClick(this);
result = true;
} else {
result = false;
}
return result;
}
总结
当事件 到达View的dispatchTouchEvent 中 该方法会先判断改View有没有实现setOnTouchListener() 如果实现了 调用onTouch 没实现 会继续 调用onTouchEvent 在 onTouchEvent中 如果View有点击事就会执行setOnTouchListener
问题思想
- 在View中 什么情况下会不执行onTouchEvent()
上面源码可以简单分析可以看出只要 实现了 setOnTouchListener 在onTouch 方法中返回了true就不会执行 onTouchEvent setOnTouchListener也一样不执行