Android源码事件传递流程剖析
2014-04-07 17:04
239 查看
这篇文章基于Android4,.2的源码分析得出,水平有限,如有错误请及时指出,谢谢!
这片文章讲解的事件传递的起源从dispatchTouchEvent(event)开始,根据事件的处理流程逐渐展开,直至事件被可预料的处理掉结束。
先贴一张个人总结的事件传递的流程图,如果可以将这张图清楚的理解,下面的文章就可以不用看了,因为这篇文章的主要内容也就是围绕这幅图展开。
一、ViewGroup中的事件处理
当事件传递到dispatchTouchEvent方法中,由于ViewGroup是View的子类,所以如果当前接收到事件的是ViewGroup将首先触发该类的dispatchTouchEvent方法(不过android界面最外层肯定是个ViewGroup所以肯定会先触发这个事件)。
该方法会先判断该事件是否可被中断(默认为是),然后便触发ViewGroup才有的onInterceptTouchEvent方法,该方法用于ViewGroup截取事件处理,假如该方法返回true则代表已经将事件截取。
在你自定义的视图中,如果想要截取事件,就可以继承onInterceptTouchEvent方法。而在ViewGroup的源码中并没有做截取动作,直接返回了false。
不管上面的那种情况最终都会通过dispatchTransformedTouchEvent方法最后调用到View中的dispatchTouchEvent方法。该方法首先会调用到的是mOnTouchListener.onTouch方法,其中mOnTouchListener是我们在使用view的setOnTouchListener方法时注册进去的监听。如果我们在注册进去监听的onTouch方法中返回true则代表该事件已经被处理,事件将不会在继续传递。
而如果没有设置监听或返回为false的话,该事件将会被传递到onTouchEvent方法。在View类的onTouchEvent方法中,由于是最简单的视图,只处理了和click相关的事件。从注释可以看出包括click和longClick事件。
在performClick中则调用到我们为view设置的clicklistener监听。
在这里我没有看到关于longClick事件的处理,暂时还没有找到,下次找到了再继续更新。
三、总结
首先接收到事件的视图是最外层的视图,然后再往子视图上传递;
事件的传递是一个递归过程;
在上述每个环节都可以通过返回true的方法,结束事件的传递;
自定义视图的事件传递过程决定于其对应继承的方法,但应该遵守上述的规则。
这片文章讲解的事件传递的起源从dispatchTouchEvent(event)开始,根据事件的处理流程逐渐展开,直至事件被可预料的处理掉结束。
先贴一张个人总结的事件传递的流程图,如果可以将这张图清楚的理解,下面的文章就可以不用看了,因为这篇文章的主要内容也就是围绕这幅图展开。
一、ViewGroup中的事件处理
当事件传递到dispatchTouchEvent方法中,由于ViewGroup是View的子类,所以如果当前接收到事件的是ViewGroup将首先触发该类的dispatchTouchEvent方法(不过android界面最外层肯定是个ViewGroup所以肯定会先触发这个事件)。
该方法会先判断该事件是否可被中断(默认为是),然后便触发ViewGroup才有的onInterceptTouchEvent方法,该方法用于ViewGroup截取事件处理,假如该方法返回true则代表已经将事件截取。
if (!disallowIntercept) { intercepted = onInterceptTouchEvent(ev); ev.setAction(action); // restore action in case it was changed } else { intercepted = false; }
在你自定义的视图中,如果想要截取事件,就可以继承onInterceptTouchEvent方法。而在ViewGroup的源码中并没有做截取动作,直接返回了false。
public boolean onInterceptTouchEvent(MotionEvent ev) { return false; }在确定事件没有被截取之后,ViewGroup中会判断自己是否有子视图符合接收该事件的条件,如果有的话,则直接将事件分发给该子视图,并返回true代表在这层事件已经被分发出去。否则的话则将该视图视为普通View继续处理事件(详细参见后面的View处理事件部分)。
if (!canViewReceivePointerEvents(child)|| !isTransformedTouchPointInView(x, y, child, null)) { continue; } newTouchTarget = getTouchTarget(child); if (newTouchTarget != null) { // Child is already receiving touch within its bounds. // Give it the new pointer in addition to the ones it is handling. newTouchTarget.pointerIdBits |= idBitsToAssign; break; } resetCancelNextUpFlag(child); if (dispatchTransformedTouchEvent(ev, false, child, idBitsToAssign)) { // Child wants to receive touch within its bounds. mLastTouchDownTime = ev.getDownTime(); mLastTouchDownIndex = childIndex; mLastTouchDownX = ev.getX(); mLastTouchDownY = ev.getY(); newTouchTarget = addTouchTarget(child, idBitsToAssign); alreadyDispatchedToNewTouchTarget = true; break; }二、View中的事件处理
不管上面的那种情况最终都会通过dispatchTransformedTouchEvent方法最后调用到View中的dispatchTouchEvent方法。该方法首先会调用到的是mOnTouchListener.onTouch方法,其中mOnTouchListener是我们在使用view的setOnTouchListener方法时注册进去的监听。如果我们在注册进去监听的onTouch方法中返回true则代表该事件已经被处理,事件将不会在继续传递。
ListenerInfo li = mListenerInfo; if (li != null && li.mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED && li.mOnTouchListener.onTouch(this, event)) { return true; } if (onTouchEvent(event)) { return true; }
而如果没有设置监听或返回为false的话,该事件将会被传递到onTouchEvent方法。在View类的onTouchEvent方法中,由于是最简单的视图,只处理了和click相关的事件。从注释可以看出包括click和longClick事件。
if (mPerformClick == null) { mPerformClick = new PerformClick(); } if (!post(mPerformClick)) { performClick(); }
在performClick中则调用到我们为view设置的clicklistener监听。
ListenerInfo li = mListenerInfo; if (li != null && li.mOnClickListener != null) { playSoundEffect(SoundEffectConstants.CLICK); li.mOnClickListener.onClick(this); return true; }
在这里我没有看到关于longClick事件的处理,暂时还没有找到,下次找到了再继续更新。
三、总结
首先接收到事件的视图是最外层的视图,然后再往子视图上传递;
事件的传递是一个递归过程;
在上述每个环节都可以通过返回true的方法,结束事件的传递;
自定义视图的事件传递过程决定于其对应继承的方法,但应该遵守上述的规则。
相关文章推荐
- Android O: 触摸事件传递流程源码分析(下)
- 手把手教你读懂源码,View的Touch事件传递流程详细剖析
- Android O: 触摸事件传递流程源码分析(上)
- Android MotionEvent事件分发机制源码剖析
- Android输入事件流程中的EventHub分析及源码演示
- android Touch事件传递机制深入剖析
- Android 开源项目源码解析 -->公共技术点之 View 事件传递(一)
- Android webkit 事件传递流程
- Android touch事件传递及View的绘制流程
- 对“Android输入事件流程中的EventHub分析及源码演示”的补充
- android View 绘制流程 和 事件传递
- Android源码剖析之Framwork层消息传递(Wms到View)
- android源码解析(三十)-->触摸事件分发流程
- Android 源码分析鼠标事件传递
- Android 源码分析AccessibilityService拦截VR眼镜Key事件以及key事件在View体系的传递
- Android事件分发机制源码剖析(1)——Activity对点击事件的分发过程
- Android事件传递机制详解及最新源码分析——View篇
- android事件传递机制---源码分析(下)
- android源码解析(二十八)-->电源开关机按键事件流程