【Android进阶笔记】事件分发机制

202 阅读1分钟

1. DOWN 事件的流向

【关键点】

  • dispatchTouchEventonTouchEvent 返回 true:事件就停止传递了(没有谁能再收到这个事件)。
  • dispatchTouchEvent 返回 false:事件停止往子 View 传递和分发同时开始往父控件回溯,就像递归停止然后开始回溯。
  • dispatchTouchEventonTouchEventonInterceptTouchEvent 返回 super.xxxxxx():事件会依照 U 型路径走完整个事件。

2. MOVE 和 UP 事件的流向

2.1. dispatchTouchEvent 返回 true

ACTION_MOVEACTION_UP 的事件传到这个 View 后就不再往下传递了,并立即消费掉。

2.2. onTouchEvent 返回 true

则 ACTION_MOVE 和 ACTION_UP 的事件传到这个 View 后就不再往下传递了,并传给自己的 onTouchEvent 消费掉。

2.3. 总结

  • ACTION_DOWN 事件在哪个控件消费了(return true), 那么 ACTION_MOVEACTION_UP 就会从上往下(通过 dispatchTouchEvent)做事件分发往下传,就只会传到这个控件,不会继续往下传。
  • 如果 ACTION_DOWN 事件是在 dispatchTouchEvent 消费,那么事件到此为止停止传递。
  • 如果 ACTION_DOWN 事件是在 onTouchEvent 消费的,那么会把 ACTION_MOVEACTION_UP 事件传给该控件的 onTouchEvent 处理并结束传递。

3. setOnTouchListener

public boolean dispatchTouchEvent(MotionEvent event) {
    // ...
    boolean result = false;
    // ...
    if (onFilterTouchEventForSecurity(event)) {
        // ...
        if (li != null && li.mOnTouchListener != null
                && (mViewFlags & ENABLED_MASK) == ENABLED
                && li.mOnTouchListener.onTouch(this, event)) {
                    // 优先处理OnTouchListener
                    // 如果返回值是true,则不会再执行自身的onTouchEvent,并消费该事件
            result = true;
        }
        // 转交给自己的onTouchEvent
        if (!result && onTouchEvent(event)) {
            result = true;
        }
    }
    // ...
    return result;
}

【结论】

  • 未设置 OnTouchListener,系统默认执行 onTouchEvent(event) 方法。
  • 设置了 OnTouchListener,系统会先执行它,并根据其返回值再决定是否执行 onTouchEvent(event)
  • OnTouchListener 的优先级比 onTouchEvent 高。