Android O: 触摸事件传递流程源码分析(下)
来源:互联网 发布:csgo mac 国服 知乎 编辑:程序博客网 时间:2024/05/17 09:12
前一篇博客中,我们分析了ViewGroup传递触摸事件的流程,详见:
Android O: 触摸事件传递流程源码分析(上)
本篇博客,我们主要来看一下View传递触摸事件的流程。
ViewGroup在分发事件时,会调用dispatchTransformedTouchEvent方法,
将MotionEvent分发给合适的Child View或ViewGroup。
对于Child View而言,dispatchTransformedTouchEvent函数,
最终还是会调用View的dispatchTouchEvent方法。
现在我们就来看看View的dispatchTouchEvent方法:
public boolean dispatchTouchEvent(MotionEvent event) { // If the event should be handled by accessibility focus first. if (event.isTargetAccessibilityFocus()) { // We don't have focus or no virtual descendant has it, do not handle the event. if (!isAccessibilityFocusedViewOrHost()) { return false; } // We have focus and got the event, then use normal event dispatch. event.setTargetAccessibilityFocus(false); } ............
从上面的代码可以看出,与ViewGroup处理MotionEvent的过程一致,
View也会先针对Accessibility Focus事件进行处理。
如果事件要求Accessibility Focus,但当前View不具备这种能力,
那么分发结束,直接返回false;
如果当前View具有Accessibility Focus能力,那么收到这种类型的事件后,
直接将MotionEvent对应的Flag置为false。
我们继续跟进代码:
//用于保存最终的结果,记录事件是否被当前View消费掉boolean result = false;//这部分应该和测试相关if (mInputEventConsistencyVerifier != null) { mInputEventConsistencyVerifier.onTouchEvent(event, 0);}//收到新开始的事件,清除旧有的记录信息final int actionMasked = event.getActionMasked();if (actionMasked == MotionEvent.ACTION_DOWN) { // Defensive cleanup for new gesture stopNestedScroll();}//与ViewGroup一样,需要进行安全性检测,避免View被恶意程序覆盖if (onFilterTouchEventForSecurity(event)) { //从注释来看,此处处理鼠标相关的输入,不用特意关注 if ((mViewFlags & ENABLED_MASK) == ENABLED && handleScrollBarDragging(event)) { result = true; } //View存在onTouchListener时,onTouchListener优先消费 ListenerInfo li = mListenerInfo; if (li != null && li.mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED && li.mOnTouchListener.onTouch(this, event)) { result = true; } //然后才是View调用onTouchEvent消费事件 //View的onTouchEvent函数,会根据事件的类型进行相应的处理 if (!result && onTouchEvent(event)) { result = true; }}//仍然是测试相关if (!result && mInputEventConsistencyVerifier != null) { mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);}// Clean up after nested scrolls if this is the end of a gesture;// also cancel it if we tried an ACTION_DOWN but we didn't want the rest// of the gesture.// 事件处理完毕或ACTION_DOWN未处理, 清楚记录if (actionMasked == MotionEvent.ACTION_UP || actionMasked == MotionEvent.ACTION_CANCEL || (actionMasked == MotionEvent.ACTION_DOWN && !result)) { stopNestedScroll();}return result;
至此,View的事件分发流程分析完毕。
可以看出,由于View不需要继续将事件分发给Child View,
因此它需要管理的状态较少,事件处理的逻辑也比ViewGroup简单。
大致上来说,View处理事件的主要逻辑如下图所示:
阅读全文