窗口是Activity的容器
窗口(Window)接收用户的点击事件并逐步向内层传递,即Window->Activity->ViewGroup->...->View
dispatchTouchEvent、onInterceptTouchEvent与onTouchEvent
- dispatchTouchEvent负责事件分发,即事件由外向内传递事件的方法
- onInterceptTouchEvent是交给ViewGroup判断是否决定需要拦截事件(不让它的子View获取事件)的方法
- onTouchEvent是View(或ViewGroup)自身消费事件的方法
MotionEvent
** MotionEvent**是对Touch事件的封装,MotionEvent主要包含以下事件类型:
- ACTION_DOWN(手指按下)
- ACTION_MOVE (手指在屏幕上移动)
- ACTION_UP (手指离开屏幕)
- ACTION_CANCEL (特殊事件,事件被取消,通常为被父类拦截)
dispatchTouchEvent伪源码(简化版源码)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| public boolean dispatchTouchEvent(MotionEvent ev) { boolean handled = false; if (ev.actionMasked == MotionEvent.ACTION_DOWN) { clearStatus(); if (!isDisallowIntercept && onInterceptTouchEvent(ev)) { isSelfNeedEvent = true; handled = onTouchEvent(ev); } else { handled = child.dipatchTouchEvent(ev); if (handled) isChildNeedEvent = true; if (!handled) { handled = onTouchEvent(ev); if (handled) isSelfNeedEvent = true; } } } else { if (isSelfNeedEvent) { handled = onTouchEvent(ev); } else { if (!isDisallowIntercept && onInterceptTouchEvent(ev)) { isSelfNeedEvent = true; boolean cancel = MotionEvent.obtain(ev); cancel.action = MotionEvent.ACTION_CANCEL; handled = child.dispatchTouchEvent(cancel); cancel.recycle(); } else { handled = child.dispatchTouchEvent(ev); } } } if(ev.actionMasked == MotionEvent.ACTION_UP || ev.actionMasked == MotionEvent.ACTION_CANCEL) { clearStatus(); } return handled; }
|
isDisallowIntercept是ViewGroup的一个成员变量,在子类调用父类的requestDisallowInterceptTouchEvent方法时会改变它的值。
onInterceptTouchEvent和requestDisallowInterceptTouchEvent
requestDisallowInterceptTouchEvent是子类在必要的时候用来告诉父类要不要拦截事件的方法。并且onInterceptTouchEvent会逐层向外传递。