0%

Android View Touch事件分发

事件是如何从屏幕点击最终到达 Activity 的?

CANCEL 事件什么时候会触发?

  1. View 收到 ACTION_DOWN 事件以后,上一个事件还没有结束(可能因为 APP 的切换、ANR 等导致系统扔掉了后续的事件),这个时候会先执行一次 ACTION_CANCEL。
  2. 子 View 之前拦截了事件,但是后面父 View 重新拦截了事件,这个时候会给子 View 发送 ACTION_CANCEL 事件。

如何解决滑动冲突?

  • 通过重写父类的 onInterceptTouchEvent 来拦截滑动事件。
  • 通过在子类中调用 parent.requestDisallowInterceptTouchEvent 来通知父类是否要拦截事件。

Touch事件分发流程

Activity -> Window -> DecorView -> ViewGroup -> View.dispatchTouchEvent()

注意点:

  • 如果在执行ACTION_DOWN时返回false,后面一系列的ACTION_MOVE、ACTION_UP事件都不会执行。
  • 如果在最上层的View的onTouchEvent在DOWN时间返回true,虽然ViewGroup的onInterceptTouchEvent()对DOWN事件返回了false,但后续的事件(MOVE、UP)依然会传递给它的onInterceptTouchEvent()
  • onInterceptTouchEvent()一旦返回一次true,就再也不会被调用了。
  • 当dispatchTouchEvent()事件分发时,只有前一个事件(如ACTION_DOWN)返回true,才会收到后一个事件(ACTION_MOVE和ACTION_UP)
  • dispatchTouchEvent()、 onTouchEvent() 消费事件、终结事件传递(返回true)
  • onInterceptTouchEvent 并不能消费事件,它相当于是一个分叉口起到分流导流的作用,对后续的ACTION_MOVE和ACTION_UP事件接收起到非常大的作用。