View事件分发机制

166 阅读1分钟

1、dispatchTouchEvent:

  public boolean dispatchTouchEvent(MotionEvent event) {
	    ......   
        boolean result = false;
		
	    ......
	    //如果当前View未被其他窗口盖住
        if (onFilterTouchEventForSecurity(event)) {
            if ((mViewFlags & ENABLED_MASK) == ENABLED && handleScrollBarDragging(event)) {
                result = true;
            }
            //noinspection SimplifiableIfStatement
            ListenerInfo li = mListenerInfo;
            (1) mOnTouchListener监听
            if (li != null && li.mOnTouchListener != null
                    && (mViewFlags & ENABLED_MASK) == ENABLED
                    && li.mOnTouchListener.onTouch(this, event)) {
                result = true;
            }
            //result为true时,onTouchEvent方法就不会调用了
            if (!result && onTouchEvent(event)) {
                result = true;
            }
        }
		......
        return result;
    }

(1)该View的mOnTouchListener!= null 并且 mOnTouchListener.onTouch(this, event)的返回值为true的时候,并且View为Enable状态时,result为true。此时onTouchEvent就不会调用了。也就是说OnTouchListener优先级比onTouchEvent要高。

2、onTouchEvent:

public boolean onTouchEvent(MotionEvent event) {
        final float x = event.getX();
        final float y = event.getY();
        final int viewFlags = mViewFlags;
        final int action = event.getAction();
		//如果View的状态为DISABLED不可以用状态
        if ((viewFlags & ENABLED_MASK) == DISABLED) {
            if (action == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) {
                setPressed(false);
            }
            //如果我们把View的点击、长按点击、上下文点击中的任意一个设置为true,则return返回truereturn (((viewFlags & CLICKABLE) == CLICKABLE
                    || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
                    || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE);
        }
        if (mTouchDelegate != null) {
            if (mTouchDelegate.onTouchEvent(event)) {
                return true;
            }
        }
		(1)//如果View的状态不是DISABLED而是ENABLED;且View的点击、长按点击、上下文点击中的任意一个设置为true
        if (((viewFlags & CLICKABLE) == CLICKABLE ||
                (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) ||
                (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE) {
            switch (action) {
                case MotionEvent.ACTION_UP:
                   ......
                            if (!focusTaken) {
                                // Use a Runnable and post this rather than calling
                                // performClick directly. This lets other visual state
                                // of the view update before click actions start.
                                if (mPerformClick == null) {
                                    mPerformClick = new PerformClick();
                                }
                                if (!post(mPerformClick)) {
                                    (2)//点击事件关键方法
                                    performClick();
                                }
                            }
                        }
						......
            return true;
        }

        return false;
    }

(1)只要View的clickable 或者longClickable有一个为true,onTouchEvent返回的为true。View的longClickable默认为false。 可点的View的clickable 为true,例如button。不可点的为false,例如textView。通过setClickable或者setOnClickListener可以将viiew的clickable设为true。
(2)当ACTION_UP事件发生时,会触发performClick方法。performClick方法内部调用onClick方法

public boolean performClick() {
    final boolean result;
    final ListenerInfo li = mListenerInfo;
    if (li != null && li.mOnClickListener != null) {
        playSoundEffect(SoundEffectConstants.CLICK);
        //点击的相关监听
        li.mOnClickListener.onClick(this);
        result = true;
    } else {
        result = false;
    }

    sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
    return result;
}