重要方法
名称 | 描述 | 事件传递 |
---|---|---|
boolean dispatchTouchEvent(ev) | 如果事件能够传递给当前View,那么此方法一定会被调用,返回结果表示是否消耗当前事件 | 返回结果受当前View的onTouchEvent和下级View的dispatchTouchEvent方法影响。 |
boolean onInterceptTouchEvent(ev) | 判断是否拦截某个事件,返回结果表示是否拦截当前事件 | 返回true,当前View的onTouchEvent(ev)方法会被调用,同一个事件序列中该方法不会再次被调用;返回false,当前事件继续传递给它的子元素 |
boolean onTouchEvent(ev) | 判断是否拦截某个事件,返回结果表示是否消耗当前事件 | 返回false,在同一个事件序列中,当前View无法再次接收到事件,它的父容器的onTouchEvent方法将会被调用 |
这三个方法之间的关系:
public boolean dispatchTouchEvent(Event ev) { boolean consume = false; if (onInterceptTouchEvent(ev)) { consume = onTouchEvent(ev); } else { consume = child.dispatchTouchEvent(ev); } return consume;}
重要结论
- 一个事件序列以
ACTION_DOWN
开始,中间含有数量不定的ACTION_MOVE
,最终以ACTION_UP
结束。 - 正常情况下,一个事件序列只能被一个View拦截且消耗。
- 某个View一旦决定拦截,那么这个事件序列都只能由它处理,并且它的onInterceptTouchEvent不会再被调用。
- 某个View一旦开始处理事件,如果它不消耗
ACTION_DOWN
,那么同一事件序列中的其他事件都不再交给它处理,事件将会重新交由它的父元素区处理。对于非ACTION_DOWN
事件,这个事件会消失,此时父元素的onTouchEvent方法不会被调用,并且当前View可以持续收到后续事件,消失的事件会传递给Activity处理。注意!!ACTION_DOWN
的消耗有些特殊。 - ViewGroup默认不拦截任何事件。
- View没有onInterceptEvent方法,如果有事件传递给它,则它的onTouchEvent方法会被调用。
- View的onTouchEvent会默认消耗消失,除非它是不可点击的。
- View的enable属性不影响onTouchEvent的返回值。
- onClick会发生的前提是当前View是可点击的,并且它收到了down和up事件。
- 事件传递过程是由外向内的,通过requestDisallowInterceptTouchEvent方法可以在子元素中干扰父元素的事件分发过程,ACTION_DOWN事件除外。
事件传递
当一个事件产生后,它会按照如下顺序传递:
Activity-->Window-->View。
即,事件总是先传递给Activity,Activity再传递给Window,Window再传给顶级View。如果所有的View都不消耗该事件,该事件最终会传递给Activity处理。
事件传递流
如下: