View事件分发二 (总结)

事件分发过程

事件分发是从Activity开始,从上到下,依次通过window,DecorView向下分发。关键的几个方法是

  • dispatchTouchEvent()
  • onInterceptTouchEvent()
  • OnTouchListener.onTouch()
  • onTouchEvent()

对于一个根ViewGroup来说,事件产生后首先会传递给他,这时他的dispatchTouchEvent()就会被调用
若这个ViewGroup的onInterceptTouchEvent()返回true,表示自己要拦截这个事件,那么他的onTouchEvent就会被调用;
若onInterceptTouchEvent()返回false,会交给子控件去处理,依次向下传递,直到事件被处理。

当一个View要处理事件时,若设置了onTouchListener,会先调用onTouch()。
若onTouch()返回true,onTouchEvent()就不会被调用了;
若onTouch()返回false,会调用onTouchEvent();
onTouchEvent若返回true,表示事件被消费,后续同一个序列的事件都会交给他来处理;
onTouchEvent若返回false,表示事件未被消费,同一个事件序列的后续事件交给其父控件来处理。若一直未被处理,Activity的onTouchEvent就会被调用。

总结伪代码如下

//整体的处理逻辑,从上级往下级分发,
//如果下级能处理了,这个事件就消费掉了,
//如果处理不了,会再传递给上级处理
boolean Parent.dispatchTouchEvent(MotionEvent ev) {
        if (child.dispatchTouchEvent(ev)) {
            return true;
        }
        boolean consume= this.onTouch();
        if(!consume){
            consume = this.onTouchEvent(ev)
        }
        return consume;
}


//ViewGroup的处理过程
//如果上级拦截了,就不向下传递,由上级处理
//如果上级不拦截,就交给下级处理,调用child的dispatchTouchEvent()
boolean viewGroup.dispatchTouchEvent(){
    boolean consume = false;
        //viewGroup拦截了事件(即重写了onInterceptTouchEvent()并返回true)
    if(onInterceptTouchEvent()){
        consume = this.onTouch()/onTouchEvent()
    }else {
        consume = child.dispatchTouchEvent();
    }
    return consume;
} 
 
 
//View的处理过程
//如果设置了onTouchListener(),onTouch()会被调用
//如果onTouch()返回true,事件消费掉
//如果onTouch()返回false,执行onTouchEvent()方法
//如果可点击且设置了setOnclickListener(),会调用onClick()
child.dispatchTouchEvent{
        //调用了setOnTouchListener()
    if(mTouchListener != null){
               //如果onTouch()返回true,直接return;
        if(onTouch()){
            return true;
        }
    }
    
    //如果onTouch()没有执行或返回的false
    onTouchEvent(){
        if(clickable == true){
            switch(event.getAction){
                               //调用了setOnClickListener()
                if(mOnclickListener != null){
                    onClick();
                }
            }
                        //往后的事件可以执行的原因
            return true;
        }
        return false;
    }
 
 }

一些结论:

  • 同一事件序列是指从手指按下开始到手指抬起结束,由一个Down,多个MOVE,一个UP组成
  • 正常情况下,一个事件序列只能被一个View拦截并消耗。
  • 某个ViewGroup一旦拦截事件,那么同一事件序列都由该ViewGroup处理,且onInterceptTouchEvent()不会再次执行。
  • 某个View开始处理事件,若不处理Down事件(onTouchEvent返回了false),那么后续事件也不会交给他来处理,而是交给父控件来处理
  • View的onTouchEvent默认是会处理事件的,除非clickable是 false
  • View的enable属性并不影响onTouchEvent的默认返回值,只要View的clickable是true,onTouchEvent就会返回true

水平有限,有错误欢迎指正

你可能感兴趣的:(View事件分发二 (总结))