事件分发的传递规则

84 阅读2分钟

事件分发的大概流程可以这样来描述:Activity ->ViewGroup ->View

事件分发需要的三个重要方法来共同完成

  • public boolean dispatchTouchEvent(event):用于进行点击事件的分发
  • public boolean onInterceptTouchEvent(event):用于进行点击事件的拦截
  • public boolean onTouchEvent(event):用于处理点击事件

三个函数的参数均为even,即上面所说的3种类型的输入事件,返回值均为boolean 类型 上面的三种方法的调用关系大致可以用下面的伪代码来描述:

    public boolean dispatchTouchEvent(MotionEvent ev) {
        boolean consume = false;//事件是否被消费
        if (onInterceptTouchEvent(ev)){//调用onInterceptTouchEvent判断是否拦截事件
            consume = onTouchEvent(ev);//如果拦截则调用自身的onTouchEvent方法
        }else{
            consume = child.dispatchTouchEvent(ev);//不拦截调用子View的dispatchTouchEvent方法
        }
        return consume;//返回值表示事件是否被消费,true事件终止,false调用父View的onTouchEvent方法
    }

onInterceptTouchEvent方法和onTouchEvent方法都在dispatchTouchEvent方法中调用。现在我们根据这段  伪代码来分析一下点击事件分发的传递规则。 

首先讲一下点击事件由上而下的传递规则,当点击事件产生后会由  Activity  来处理,传递给  PhoneWindow,再传递给DecorView,最后传递给顶层的ViewGroup。一般在事件传递中只考虑 ViewGroup  的 onInterceptTouchEvent 方法,因为一般情况下我们不会重写 dispatchTouch-Event()方法。对于根  ViewGroup,点击事件首先传递给它的dispatchTouchEvent()方法,如果该ViewGroup的  onInterceptTouchEvent()方法返回true,则表示它要拦截这个事件,这个事件就会交给它的  onTouchEvent()方法处理;如果onInterceptTouchEvent()方法返回false,则表示它不拦截这个事件,则  这个事件会交给它的子元素的dispatchTouchEvent()来处理,如此反复下去。如果传递给底层的View,  View是没有子View的,就会调用View的dispatchTouchEvent()方法,一般情况下最终会调用View的  onTouchEvent()方法。

接下来讲解点击事件由下而上的传递。当点击事件传给底层的 View 时,如果其onTouchEvent()方法  返回true,则事件由底层的View消耗并处理;如果返回false则表示该View不做处理,则传递给父View的  onTouchEvent()处理;如果父View的onTouchEvent()仍旧返回false,则继续传递给该父View的父View  处理,如此反复下去。