美文网首页
事件分发机制

事件分发机制

作者: C调路过 | 来源:发表于2020-03-18 02:00 被阅读0次

    先从底端的View看起。

    public class View {
    
        // 经过Activity与ViewGroup的分发到了View
        public boolean dispatchTouchEvent(MotionEvent event) {
    
            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;
            }
        }
        
        //如果设置了onTouchListener 执行回调函数onTouch
        public boolean onTouchEvent(MotionEvent event) {
    
            if (clickable || (viewFlags & TOOLTIP) == TOOLTIP) {
                switch (action) {
                    case MotionEvent.ACTION_UP:
                        performClick();
                    ...
                }
                return true;
            }
        }
    
        // 执行OnClickListener回调消耗事件
        public boolean performClick() {
    
            final boolean result;
            final ListenerInfo li = mListenerInfo;
            if (li != null && li.mOnClickListener != null) {
                li.mOnClickListener.onClick(this);
                result = true;
            } else {
                result = false;
            }
    
            return result;
        }
    
    }
    

    ViewGroup相较View多了拦截处理和给子View分发的操作。

    public class ViewGroup{
        public boolean dispatchTouchEvent(MotionEvent ev) {
            // Check for interception.
            final boolean intercepted;
            if (actionMasked == MotionEvent.ACTION_DOWN
                    || mFirstTouchTarget != null) {
                final boolean disallowIntercept = (mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0;
                if (!disallowIntercept) {
                    intercepted = onInterceptTouchEvent(ev);
                    ev.setAction(action); // restore action in case it was changed
                } else {
                    intercepted = false;
                }
            } else {
    
                intercepted = true;
            }
    
            if (!canceled && !intercepted) {
                for (int i = childrenCount - 1; i >= 0; i--) {
                    final int childIndex = getAndVerifyPreorderedIndex(
                            childrenCount, i, customOrder);
                    final View child = getAndVerifyPreorderedView(
                            preorderedList, children, childIndex);
    
                    //子View处理了事件
                    if (dispatchTransformedTouchEvent(ev, false, child, idBitsToAssign)) {
                        // Child wants to receive touch within its bounds.
                        mLastTouchDownTime = ev.getDownTime();
                        if (preorderedList != null) {
                            // childIndex points into presorted list, find original index
                            for (int j = 0; j < childrenCount; j++) {
                                if (children[childIndex] == mChildren[j]) {
                                    mLastTouchDownIndex = j;
                                    break;
                                }
                            }
                        } else {
                            mLastTouchDownIndex = childIndex;
                        }
                        mLastTouchDownX = ev.getX();
                        mLastTouchDownY = ev.getY();
                        newTouchTarget = addTouchTarget(child, idBitsToAssign);
                        alreadyDispatchedToNewTouchTarget = true;
                        break;
                    }
                    
                    // 如果子View都没有处理,或者View.onTouch 返回false
    
                    if (mFirstTouchTarget == null) {
                        // No touch targets so treat this as an ordinary view.
                        handled = dispatchTransformedTouchEvent(ev, canceled, null,
                                TouchTarget.ALL_POINTER_IDS);
                    }
                }
            }
        }
    
        //让子View去尝试执行
        private boolean dispatchTransformedTouchEvent(MotionEvent event, boolean cancel,
                                                      View child, int desiredPointerIdBits) {
            final boolean handled;
    
            // 如果子View都没有处理,或者View.onTouch 返回false ,将会掉父类View的dispatchTouchEvent,将自己当成View去处理onTouch onTouchEvent和performClick
            if (child == null) {
                handled = super.dispatchTouchEvent(transformedEvent);
            } else {
                final float offsetX = mScrollX - child.mLeft;
                final float offsetY = mScrollY - child.mTop;
                transformedEvent.offsetLocation(offsetX, offsetY);
                if (!child.hasIdentityMatrix()) {
                    transformedEvent.transform(child.getInverseMatrix());
                }
    
                handled = child.dispatchTouchEvent(transformedEvent);
            }
            
            return handled;
    
        }
            
    }
    

    大致可理解为伪代码如下

    public boolean dispatchTouchEvent(MotionEvent ev){
        
        boolean consume;
        
        if(onInterceptTouchEvent(ev)){
            consume = onTouchEvent(ev);
        }else {
            consume = child.dispatchTouchEvent(ev);
        }
        
        return consume;
    }
    

    再向上传递到Activity实际是顶部View DecorView做的处理,与ViewGroup无二意。
    反过来从Activity->ViewGroup->View 就是事件分发的流程。

    相关文章

      网友评论

          本文标题:事件分发机制

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