@act262
2017-05-24T14:25:42.000000Z
字数 2602
阅读 1157
AndroidSource
触摸事件从硬件层产生,由系统分发至当前应用,再由当前应用分发到前台展示的Activity,其中Activity这一层不是必须的.
屏幕触摸 -> Activity -> Window -> RootView -> View
整个调用链中使用了责任链的设计模式,将事件一层一层往下传递,如果被下层处理了,就不会返回上层了,上层也就不需要处理了,如果下层也不处理,那么原路返回上层,让上层去处理这个事件.
Activity.java
public boolean dispatchTouchEvent(MotionEvent ev) {if (ev.getAction() == MotionEvent.ACTION_DOWN) {onUserInteraction();}if (getWindow().superDispatchTouchEvent(ev)) {return true;}// 下层没有消费掉事件,则交给自己的onTouchEvent处理return onTouchEvent(ev);}public boolean onTouchEvent(MotionEvent event) {if (mWindow.shouldCloseOnTouch(this, event)) {finish();return true;}return false;}
Window.java
public abstract boolean superDispatchTouchEvent(MotionEvent event);
Window的具体实现类是PhoneWindow
public boolean superDispatchTouchEvent(MotionEvent event) {return mDecor.superDispatchTouchEvent(event);}
这里的mDecor是DecorView extends FrameLayout即ViewGroup
public boolean superDispatchTouchEvent(MotionEvent event) {return super.dispatchTouchEvent(event);}
所以流程跳转到了ViewGroup的dispatchTouchEvent方法
public boolean dispatchTouchEvent(MotionEvent ev) {// ...// ViewGroup的这里需要特殊处理拦截的处理if (!disallowIntercept) {intercepted = onInterceptTouchEvent(ev);ev.setAction(action); // restore action in case it was changed} else {intercepted = false;}childView.dispatchTouchEvent();}public boolean onInterceptTouchEvent(MotionEvent ev) {if (ev.isFromSource(InputDevice.SOURCE_MOUSE)&& ev.getAction() == MotionEvent.ACTION_DOWN&& ev.isButtonPressed(MotionEvent.BUTTON_PRIMARY)&& isOnScrollbarThumb(ev.getX(), ev.getY())) {return true;}return false;}public boolean onToucheEvent(MotionEvent ev) {// 继承自View的onTouchEvent方法}
最后是到最后子节点的View来处理或者不处理
public boolean dispatchTouchEvent(MotionEvent event) {// ...// 如果设置了OnTouchListener,则OnTouchListener可以优先处理ListenerInfo li = mListenerInfo;if (li != null && li.mOnTouchListener != null&& (mViewFlags & ENABLED_MASK) == ENABLED&& li.mOnTouchListener.onTouch(this, event)) {result = true;}// 前面的OnTouchListener没有消费掉,那么就交给自己的onTouchEvent来来处理if (!result && onTouchEvent(event)) {result = true;}}public boolean onTouchEvent(MotionEvent event) {// ... 这里对点击,长按等处理switch (action) {case MotionEvent.ACTION_UP:// ...if (mPerformClick == null) {mPerformClick = new PerformClick();}// 处理点击的情况,执行点击if (!post(mPerformClick)) {performClick();}if (mUnsetPressedState == null) {mUnsetPressedState = new UnsetPressedState();}// 点击完后变成非按压状态if (prepressed) {postDelayed(mUnsetPressedState,ViewConfiguration.getPressedStateDuration());} else if (!post(mUnsetPressedState)) {// If the post failed, unpress right nowmUnsetPressedState.run();}break;case MotionEvent.ACTION_DOWN:// Not inside a scrolling container, so show the feedback right away// 变成按压状态,同时检测是否变成长按状态setPressed(true, x, y);checkForLongClick(0, x, y);// ...// 默认是没有处理的,所以会给上层有机会处理return false;}
由最底层View返回是否消费掉事件