以前对Android的事件分发一直都不是很熟悉,所以找了个时间 仔细研究了一下android源码终于把困扰我多时的问题解决了
首先 我们假设一个场景 一个LinearLayout 里面放入一个Button 那么事件怎样分发的呢,
Button继承自TextView 而TextView继承自View 当Button点击的时候 会从 父布局向上查找 dispatchTouchEvent方法进行处理,当然我们也可以自定义一个LinearLayout
然后重写其中的dispatchTouchEvent方法 如果没有重写 父布局会一层层向上级布局查找,最后我们可以在ViewGroup中找到这个方法 查看这个方法的源码可以发现
进入此方法以后首先执行的是一个if条件判断
if (disallowIntercept || !onInterceptTouchEvent(ev))
判断的条件第一个条件默认为false 当第二个条件为true时 就可以进入if的内部执行
onInterceptTouchEvent 这个 方法大家应该都不陌生,当此方法的返回值为false时 就会进入 if内部 查看内部的代码 可以得知 if内部主要 就是判断view是否被点击
当被点击后会执行view的dispatchTouchEvent方法 此方法虽然和ViewGroup的dispatchTouchEvent方法名称相同 但是其中的代码却完全不同
public boolean dispatchTouchEvent(MotionEvent event) {
if (mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED &&
mOnTouchListener.onTouch(this, event)) {
return true;
}
return onTouchEvent(event);
}
view的此方法较简单 通过分析我们可以看出 返回值为true 需要满足三个条件
1,相应的View设置了onTouchListener
2. 当前的view是可以点击的 Button默认是可以点击的 但是当我们点击的对象是ImageView的时候 就不同了此种情况需另考虑
3.第三个就是onTouch的返回值 当此方法的返回值为true时 会直接返回true 返回值为false时 会执行 onTouchEvent方法 此方法的内部 执行了onClick方法
总结一下:
当我们点击一个View的时候 会先从它的父布局中查找dispatchTouchEvent方法 找到此方法后 会判断onInterceptTouchEvent 当此返回值为false时 会执行view的dispatchTouchEvent的方法 进入此方法以后 会判断 是否设置了onTouchListener方法 和onTouch方法的返回值 如果没有设置监听或者返回值为false 则会执行onTouchEvent方法方法中封装了onClick方法 就会执行