View的事件分发机制
在android中,点击的事件分发就是对MotionEvent的分发,当一个点击事件产生后,传递过程应该是:Activity->Window->DecorView->CustomView。
事件分发这个过程由三个重要方法来完成:
1. public boolean dispatchTouchEvent(MotionEvent event)
用于进行事件的分发。如果事件能传递到当前View,此方法必定会被调用,返回结果受当前View的onTouchEvent和下级View的dispatchTouchEvent方法影响。
- true 消费事件。
- false 不向下分发事件,交由上层控件的onTouchEvent消费。如果当前控件为Activity,那么事件会被系统消费。
- super.dispatchTouchEvent(event) 交给本层控件的onInterceptTouchEvent处理。
2. public boolean onInterceptTouchEvent(MotionEvent ev)
在dispatchTouchEvent方法内部调用,此方法只存在ViewGroup中。表示是否拦截事件。拦截时只会调用一次。
- true 拦截事件,本层onTouchEvent处理。
- false 不拦截,分发到子View。由子View的dispatchTouchEvent处理。
- super.onInterceptTouchEvent(event) 默认为不拦截任何事件。
3. public boolean onTouchEvent(MotionEvent event)
在dispatchTouchEvent方法内部调用,用于处理点击事件。
- true 表示处理完事件后消费掉。
- false 不处理事件,交由上层View的onTouchEvent方法处理,如果一直返回false直到Activity,那么由Activity的onTouchEvent处理。
- super.onTouchEvent(event) 如果此View为可点击的,默认返回true。
下面用代码解释以下几种情况:
- 默认情况。
- ViewGroup拦截事件,即onInterceptTouchEvent返回true。
- 子View的onTouchEvent返回false,则会往上分发。

- 解释:默认情况下,从Activity->ViewGroup->View分发到子View上的onTouchEvent上消费。

- 解释:在ViewGroup上拦截事件,即onInterceptTouchEvent返回true。除了在DOWN的时候调用了一次onInterceptTouchEvent外,后面的MOVE和UP都没有再次调用,说明拦截方法在同一触摸事件中只执行一次。
ViewGroup的onTouchEvent默认不消费,所以向上分发到Activity的onTouchEvent中消费。

- 解释:在ViewGroup不拦截也不消费的情况下,子View的onTouchEvent也不消费,那么会向上分发,一直到Activity才被消费。
总结:

网友评论