美文网首页
Android 事件分发总结

Android 事件分发总结

作者: atmanye | 来源:发表于2020-05-21 16:36 被阅读0次

一、View事件分发

先看看这几种现象
View与Touch事件相关的两个方法

1.1 dispatchTouchEvent事件分发
源码中,首先将result = false;
boolean result = false;
再拿到ListenerInfo, 存放了关于View的所有Listener信息如 OnTouchListener 、OnClickListener等
ListenerInfo li = mListenerInfo;
若onTouchListener.onTouch()返回true,则result置为true;

            ListenerInfo li = mListenerInfo;
            if (li != null && li.mOnTouchListener != null
                    && (mViewFlags & ENABLED_MASK) == ENABLED
                    && li.mOnTouchListener.onTouch(this, event)) {
                result = true;
            }

再往下看, 如果 result = false 就会执行onTouchEvent; 如果result = true 就不会执行onTouchEven,这里就解释了,会先执行onTouchListener中的方法。

            if (!result && onTouchEvent(event)) {
                result = true;
            }

目前还未看到有点击事件onClick(),进入到onTouchEvent()中,
case MotionEvent.ACTION_UP: 里面调用了 performClick()

switch (action) { 
                case MotionEvent.ACTION_UP:              
                            //.....其他代码省略    
                                if (mPerformClick == null) {
                                    mPerformClick = new PerformClick();
                                }       
                                if (!post(mPerformClick)) {
                                      performClickInternal();
                               }

所以当onTouchEvent()返回true时,不会执行onClick(),又或者说只有当调用了onTouchEvent的super()方法时,才会执行onClcik().
因为onClick()方法是在View.onTouchEvent的super()方法中。

二、ViewGroup事件分发

**dispatchTouchEvent() **事件分发:

boolean handled = false;
final int action = ev.getAction();
final int actionMasked = action & MotionEvent.ACTION_MASK;

ACTION_DOWN事件中,先将TouchTargets 清除,
并且将
mFirstTouchTarget = null

           if (actionMasked == MotionEvent.ACTION_DOWN) {
              // 清除TouchTargets 只要知道 mFirstTouchTarget = null
                cancelAndClearTouchTargets(ev);
                resetTouchState();
            }

再到onInterceptTouchEvent()事件,正常情况返回false;
onInterceptTouchEvent()返回false时,反序获取子View,执行子View的dispatchTouchEvent()方法;onInterceptTouchEvent()返回true时,将不执行子view的方法。

             //是否拦截
            final boolean intercepted;
            if (actionMasked == MotionEvent.ACTION_DOWN
                    || mFirstTouchTarget != null) {
                //子类是否请求拦截
                final boolean disallowIntercept = (mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0;
                if (!disallowIntercept) {
                    //正常情况下,会走到onInterceptTouchEvent()中
                    intercepted = onInterceptTouchEvent(ev);
                    ev.setAction(action); 
                } else {
                    intercepted = false;
                }
            } else {
                intercepted = true;
            }
            if (!canceled && !intercepted) {
                    if (newTouchTarget == null && childrenCount != 0) {
                        for (int i = childrenCount - 1; i >= 0; i--) {
                            // 反序的for循环  获取子 View child,执行子类的dispatchTouchEvent
                            //这里如果子类没有一个地方返回true,默认是返回false,则不会进入判断
                            if (dispatchTransformedTouchEvent(ev, false, child, idBitsToAssign)) {
                                // 如果子 View 返回true 就会进来 主要给 mFirstTouchTarget = target; 
                                // 这种情况,move和up事件进来的时候,不会调用子view 的dispatchTouchEvent事件。
                                // 最后调用到自己的dispatchTouchEvent事件,也就是ViewGroup的。
                                newTouchTarget = addTouchTarget(child, idBitsToAssign);
                                 break;

三、总结

最后贴个图总结下


相关文章

网友评论

      本文标题:Android 事件分发总结

      本文链接:https://www.haomeiwen.com/subject/lrdzohtx.html