主要写三个方面:
1,事件分发分发的是什么事件(ACTION_DOWN,ACTION_MOVE,ACTION_UP,ACTION_CANCEL(事件被上层拦截的时候触发))
2,事件是怎么处理(通过对ontouch,onclick之间的关系解析)
举一个案例,一个按钮同时监听ontouch,onclick,在ontouch()返回true,这时发现onclick没有被触发。通过这个现象我看了下源码中的事件处理流程,可以在源码中找到以下的代码段。
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); } 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(); } if (onFiltertouchEventForSecurity(event)) { if ((mVIEwFlags & ENABLED_MASK) == ENABLED && handleScrollbarDragging(event)) { result = true; } //noinspection SimplifiableIfStatement ListenerInfo li = mListenerInfo; if (li != null && li.mOntouchListener != null && (mVIEwFlags & ENABLED_MASK) == ENABLED && li.mOntouchListener.ontouch(this, event)) { result = true; } 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. if (actionMasked == MotionEvent.ACTION_UP || actionMasked == MotionEvent.ACTION_CANCEL || (actionMasked == MotionEvent.ACTION_DOWN && !result)) { stopnestedScroll(); } return result; }
这个现象造成的原因就在上面,我把主要的语句摘录出来
ListenerInfo li = mListenerInfo; if (li != null && li.mOntouchListener != null && (mVIEwFlags & ENABLED_MASK) == ENABLED && li.mOntouchListener.ontouch(this, event)) { result = true; } if (!result && ontouchEvent(event)) { result = true; }
可以看到当ontouch()返回true时,result会被赋值为true,而按钮的的onclick()其实是在ontouchEvent()执行的,所以不会执行到,这就是onclick()没有执行的原因了。(如果大家想验证下我们可以看看ontouchEvent()这个函数的实现。在case MotionEvent.ACTION_UP:可以找到performClick();这个函数,我们再次进入这个函数就可以看到我们的我们的li.mOnClickListener.onClick(this);)
也就是说我们事件具体的处理其实主要在VIEw的dispatchtouchEvent()和VIEw的ontouchEvent().这个时候如果我们要进入onclick()那么我们就把ontouch()返回false就可以啦。而如果我们想让ontouch()返回true,还想触发onclick(),那么我们可以在需要的动作中手动调用v.performClick();
3,分析源码,了解事件冲突的原因以及解决
总结
以上是内存溢出为你收集整理的Android事件分发源码剖析(一)之事件处理全部内容,希望文章能够帮你解决Android事件分发源码剖析(一)之事件处理所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)