Android源码事件传递流程剖析
来源:互联网 发布:淘宝炫舞摘花怎么样 编辑:程序博客网 时间:2024/06/06 00:38
这篇文章基于Android4,.2的源码分析得出,水平有限,如有错误请及时指出,谢谢!
这片文章讲解的事件传递的起源从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();}
ListenerInfo li = mListenerInfo;if (li != null && li.mOnClickListener != null) {playSoundEffect(SoundEffectConstants.CLICK);li.mOnClickListener.onClick(this);return true;}
在这里我没有看到关于longClick事件的处理,暂时还没有找到,下次找到了再继续更新。
三、总结
- 首先接收到事件的视图是最外层的视图,然后再往子视图上传递;
- 事件的传递是一个递归过程;
- 在上述每个环节都可以通过返回true的方法,结束事件的传递;
- 自定义视图的事件传递过程决定于其对应继承的方法,但应该遵守上述的规则。
0 0
- Android源码事件传递流程剖析
- Android事件传递流程
- 从源码角度分析Android 事件传递流程
- Android O: 触摸事件传递流程源码分析(上)
- Android O: 触摸事件传递流程源码分析(下)
- Android webkit 事件传递流程
- Android 耳机事件传递流程
- Android Touch事件传递流程
- Android按键事件传递流程
- android Touch事件传递机制深入剖析
- android input 事件传递主要流程
- Android 触摸事件传递流程解析
- Android webkit 事件传递流程通道分析
- android View 绘制流程 和 事件传递
- android事件传递流程 onTouchEvent onInterceptTouchEvent()
- Android按键事件传递流程(二)
- Android按键事件传递流程(一)
- Android事件传递流程-伪代码
- A Note On Practice And Persistence
- 黑马程序员-get,set提交
- OWIN
- poj--1753 Flip Game(二维反转)(高斯消元)
- JUnit白盒测试-第1天
- Android源码事件传递流程剖析
- 在windows上如何收集性能资料的一个开源工具
- TMS320DM8168达芬奇视频片上系统(SoC)的系统特
- Python基础 2:duck type
- webview中处理js的对话框
- OCP-1Z0-051 第3题 转义字符
- 熟记四原则 白领远离亚健康
- JUnit白盒测试-第2天
- CentOS6.3 系统中su,su -,sudo三命令讲解