参考:https://xiaozhuanlan.com/topic/8946537021
从触摸屏幕到事件在底层传输最终会到:
private int processPointerEvent(QueuedInputEvent q) { final MotionEvent event = (MotionEvent)q.mEvent; mAttachInfo.mUnbufferedDispatchRequested = false; // 获取到事件传递对象 mView final View eventTarget = (event.isFromSource(InputDevice.SOURCE_MOUSE) && mCapturingView != null) ? mCapturingView : mView; mAttachInfo.mHandlingPointerEvent = true; // 调用方法进行事件派发 boolean handled = eventTarget.dispatchPointerEvent(event); ... // 如果事件被处理,则结束input stage pipeline,如果否,则继续派发到下一stage return handled ? FINISH_HANDLED : FORWARD; }
dispatchPointerEvent为整个视图树派发的入口,其中的View是调用addView时传给ViewRootImpl的。
这块的流程我在之前的Activity视图显示分析中提到过,mView实际上是DecorView的实例。
在View中:
public final boolean dispatchPointerEvent(MotionEvent event) { if (event.isTouchEvent()) { return dispatchTouchEvent(event); // 随后会分发到ViewGroup或View的对应方法 } else { return dispatchGenericMotionEvent(event); } }
DecorView并没有覆写dispatchPointerEvent方法,直接调用的父类View的实现,随后会调用DecorView的dispatchTouchEvent方法:
@Override public boolean dispatchTouchEvent(MotionEvent ev) { final Window.Callback cb = mWindow.getCallback(); return cb != null && !mWindow.isDestroyed() && mFeatureId < 0 ? cb.dispatchTouchEvent(ev) : super.dispatchTouchEvent(ev); }
我们可以看到会调用Window.Callback这个接口的cb.dispatchTouchEvent(ev)方法
public class Activity extends ContextThemeWrapper implements LayoutInflater.Factory2, Window.Callback, KeyEvent.Callback, OnCreateContextMenuListener, ComponentCallbacks2, Window.OnWindowDismissedCallback, WindowControllerCallback, AutofillManager.AutofillClient {
其中Activity实现了这个接口,需要重写里面的dispatchTouchEvent()方法:
public boolean dispatchTouchEvent(MotionEvent ev) { if (ev.getAction() == MotionEvent.ACTION_DOWN) { onUserInteraction(); } if (getWindow().superDispatchTouchEvent(ev)) { return true; } return onTouchEvent(ev); }
至此进入我们的View事件分发的机制。