Android事件分发机制

220 阅读2分钟
  • 要点
    • 所谓事件分发,就是对MotionEvent一系列事件的分发,包括ACTION_DOWN、ACTION_MOVE、ACTION_UP
    • 每次分发都是从ACTION_DOWN开始,到ACTION_UP为结束,过程是ACTION_MOVE.其中ACTION_DOWN、ACTION_UP只有一次,ACTION_MOVE多次
    • 当一个事件产生后,传递过程遵循如下顺序:
    • 底层中断上报 -> Activity -> Window -> View
      (即Activity -> Window -> PhoneWindow-> DecorView -> View)
    • 相关方法:
      • dispatchTouchEvent
      • onInterceptTouchEvent
      • onTouchEvent
      • 触摸事件onTouch
      • 点击事件onClick/onLongClick
    • 整个时间是个责任链模式传递的.事件传递过程是由外向内的,即事件总是先传递给父元素,然后再由父元素分发给子View,子元素可以通过调用parentView.requestDisallowInterceptTouchEvent方法,来设置disallowIntercept=true,从而阻止父ViewGroup的onInterceptTouchEvent拦截操作,但是ACTION_DOWN事件除外
    • 伪代码:

public void dispatchTouchEvent(MotionEvent ev) {
    boolean consume = false;
    if (onInterceptTouchEvent(ev)) {
        //根据触摸监听的返回值决定是否consume
        if (mOnTouchListener != null && view是enable的) {
            if (mOnTouchListener.onTouch(ev)) {
               consume = true; 
            } else {
                //在onTouchEvent方法中,如果设置了点击事件,则点击事件会被响应
               consume = onTouchEvent(ev); //默认可点击或可长按则返回true
            }
        } else {
            //在onTouchEvent方法中,如果设置了点击事件,则点击事件会被响应
            consume = onTouchEvent(ev); //默认可点击或可长按则返回true
        }
    } else {
        consume = child.dispatchTouchEvent(ev);
    }
    return consume;
}

  • 伪代码注意点:
    • ViewGroup默认不拦截任何事件。ViewGroup的onInterceptTouchEvent方法默认返回false。
    • View没有onInterceptTouchEvent方法,一旦有点击事件传递给它,那么它的onTouchEvent方法就会被调用。
  • activity#dispatchTouchEvent是入口(实际上我们可以理解为DecorView#dispatchTouchEvent的才是入口,如果activity重写了dispatchTouchEvent,就会调用,否则会直接调用viewgroup#dispatchTouchEvent;
  • activity#dispatchTouchEvent默认也会调用viewgroup#dispatchTouchEvent)
  • 如果所有view都不处理,最后会交给activity#onTouchEvent
  • 一张图概括上面的流程

  • 疑问点:onInterceptTouchEvent的返回值,好像会根据view的类型,有所区别,具体问题具体分析吧...


相关连接:
  1. Android艺术探索
  2. gityuan.com/2015/09/19/…