类型 | 相关方法 | Activity | ViewGroup | View |
---|---|---|---|---|
事件分发 | dispatchTouuchEvent | Y | Y | Y |
事件拦截 | onInterceptTouchEvent | N | Y | N |
事件消费 | onTouchEvent | Y | Y | Y |
View的dispatchTouchEvent源码:
ListenerInfo li = mListenerInfo;
if (li != null && li.mOnTouchListener != null
&& (mViewFlags & ENABLED_MASK) == ENABLED
&& li.mOnTouchListener.onTouch(this, event)) {
result = true;
}
if (!result && onTouchEvent(event)) {
result = true;
}
消费View事件的两种方式
- onTouch
View对象可以通过setOnClickListener来设置一个Event的监听者,这样当事件来临时,View会主动调用listener来告知对方。从优先级来看,这种方式较下面的onTouchEvent先行处理。 - onTouchEvent
假如用户没有指定OntouchListener,或者flags被指明为disabled,又或者onTouch的返回值为false(代表这一事件没有被处理),那么系统会将event传给onTouchEvent。
可知,onTouch 优先于 onTouchEvent执行
MotionEvent有多种类型,常见有:
- ACTION_DOWN
- ACTION_MOVE
- ACTION_UP
ViewGroup的dispatchTouchEvent源码:
boolean handled = false;
if (onFilterTouchEventForSecurity(ev)) {
final int action = ev.getAction();
final int actionMasked = action & MotionEvent.ACTION_MASK;
// Handle an initial down.
if (actionMasked == MotionEvent.ACTION_DOWN) {
// Throw away all previous state when starting a new touch gesture.
// The framework may have dropped the up or cancel event for the previous gesture
// due to an app switch, ANR, or some other state change.
cancelAndClearTouchTargets(ev);
resetTouchState();
}
// Check for interception.
final boolean intercepted;
if (actionMasked == MotionEvent.ACTION_DOWN
|| mFirstTouchTarget != null) {
final boolean disallowIntercept = (mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0;
if (!disallowIntercept) {
intercepted = onInterceptTouchEvent(ev);
ev.setAction(action); // restore action in case it was changed
} else {
intercepted = false;
}
} else {
// There are no touch targets and this action is not an initial down
// so this view group continues to intercept touches.
intercepted = true;
}
// If intercepted, start normal event dispatch. Also if there is already
// a view that is handling the gesture, do normal event dispatch.
if (intercepted || mFirstTouchTarget != null) {
ev.setTargetAccessibilityFocus(false);
}
// Check for cancelation.
final boolean canceled = resetCancelNextUpFlag(this)
|| actionMasked == MotionEvent.ACTION_CANCEL;
// Update list of touch targets for pointer down, if needed.
final boolean split = (mGroupFlags & FLAG_SPLIT_MOTION_EVENTS) != 0;
TouchTarget newTouchTarget = null;
boolean alreadyDispatchedToNewTouchTarget = false;
if (!canceled && !intercepted) {
...//when intercepted is false.
}
- ViewGroup是继承自View
- 事件传递的顺序
Activity -> PhoneWindow -> DecorView(由ActionBar和ContentView组成) -> ViewGroup -> ... -> View