Skip to content

Latest commit

 

History

History
63 lines (33 loc) · 3.99 KB

6. View 的事件分发机制.md

File metadata and controls

63 lines (33 loc) · 3.99 KB
  1. View 的事件分发机制 ==

图:Android Touch 事件传递机制


1. ViewGroup 上看

如果点击一个 ViewGroup 的话,点击事件产生之后:

  • 1.1 首先会传递给这个 ViewGroup

  • 1.2 然后调用该 ViewGroupdispatchTouchEvent 分发事件。

  • 1.3.1 如果 ViewGrouponInterceptTouchEvent 返回 true,则表示 拦截事件。接着会将该事件交给该 ViewGroup 处理,调用其 onTouchEvent

  • 1.3.2 如果 ViewGrouponInterceptTouchEvent 返回 false,则表示 不拦截事件。这个事件就会交给 ViewGroup 的 子 View 去处理。接着 在 子 View 中 继续循环 1.1、1.2、1.3.1、1.3.2

2. onTouchListener > onTouchEvent > onClickListener

一个 View 需要处理事件的时候,如果设置了 onTouchListener。那么,接着这个 onTouchListeneronTouch 方法会别调用。

  • 2.1 如果 onTouch 返回 true。那么 onTouchEvent 会被调用。
  • 2.1.1onTouchEvent 中,如果设置了 onClickListener。会调用 performClick(),接着就回调了 OnClickListener.onClick(View v)

所以:
onTouchListener > onTouchEvent > onClickListener


3. Activity 上看

一个点击事件触发后,会有如下的传递过程:Activity >> Window >> View(从上到下)

如果,中间没有拦截,传到最底下的 View 时,会从 最底下的 View 开始 调用 onTouchEvent 方法,如果一直返回 false 的话,就调用 父 ViewonTouchEvent 方法 ,直到 Activity 为止。所以,如果 onTouchEvent 一直返回 false 的过程是:最底层 View.onTouchEvent >> 倒数第二层 View.onTouchEvent >> Activity.onTouchEvent(从下到上)


一些有用的结论

  • 1. 同一个序列的事件:手机按下屏幕到离开屏幕的过程。这个过程以 down 事件开始,然后到 N 次 的 move 事件,最后以 up 事件结束。

  • 2. 正常情况下,一个事件序列只能被一个 View 拦截并且消费

  • 3. 一个 View 拦截了事件后,这一序列的事件都会交给该 View 执行处理。因此,同一个序列事件不能分别交给两个 View 同时处理。但是有特殊手段能做到,比如:在一个 View 的 onTouchEvent 内交给其他 View 处理

  • 4. 在同一序列事件的情况下,如果 View 拦截了事件,那么后续的事件都由该 View 去处理,并且不会再该序列事件中调用 onInterceptTouchEvent

  • 5. 如果 View 不消费 DOWN 以外的事件,这个事件消失。父元素的 onTouchEvent 也不会调用。并且当前 View 可以持续收到后续事件,那么之前消失的事件会传递到 Activity 中进行处理

  • 6. ViewGroup 默认不拦截事件,源码中 ViewGrouponInterceptTouchEvent 方法默认返回 false

  • 7. View 没有 onInterceptTouchEvent 方法,如果有事件传递给它,那么它的 onTouchEvent 方法会被调用。

  • 8. ViewonTouchEvent 事件默认会被消费。除非它被设置为不可点击状态( clickable or longClickable == false )。

  • 9. Viewenable 属性不会影响 onTouchEvent 方法的返回值。只要 clickable or longClickable == true,那么 onTouchEvent 方法 就会返回 true

  • 10. onClick 发生的前提是当前 View 是可点击的。并且接收到了 DOWN 事件。

  • 11. 事件的传递过程是 由外向内 的。事件会从 Activity >> Window >> View 传递给父元素,然后一直传递给子元素。在子元素中可以通过 requestDisallowInterceptTouchEvent 方法干预父元素的分发。但 DOWN 事件除外。