1.onTouch & onTouchEvent

onTouch先调用, onTouchEvent后调用 如果onTouch()返回true, onTouchEvent()就不会调用 其中,ListenerInfo是一个监听器的集合

public class View{
    public boolean dispatchTouchEvent(MotionEvent event) {
        boolean result = false;
		
		...

        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;
            }
        }

        ...

        return result;
    }
	
	static class ListenerInfo {
        protected OnFocusChangeListener mOnFocusChangeListener;
        private ArrayList<OnLayoutChangeListener> mOnLayoutChangeListeners;
        protected OnScrollChangeListener mOnScrollChangeListener;
        private CopyOnWriteArrayList<OnAttachStateChangeListener> mOnAttachStateChangeListeners;
        public OnClickListener mOnClickListener;
        protected OnLongClickListener mOnLongClickListener;
        protected OnContextClickListener mOnContextClickListener;
        protected OnCreateContextMenuListener mOnCreateContextMenuListener;
        private OnKeyListener mOnKeyListener;
        private OnTouchListener mOnTouchListener;
        private OnHoverListener mOnHoverListener;
        private OnGenericMotionListener mOnGenericMotionListener;
        private OnDragListener mOnDragListener;
        private OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener;
        OnApplyWindowInsetsListener mOnApplyWindowInsetsListener;
        OnCapturedPointerListener mOnCapturedPointerListener;
        private ArrayList<OnUnhandledKeyEventListener> mUnhandledKeyListeners;
    }
}

2.Custom view TestView overrides onTouchEvent but not performClick more…

View的点击事件实际是在onTouchEvent()中触发的,所以如果override了onTouchEvent,onClickListener 的onClick()就有可能调用不到,所以就会给上述提示。

同理,结合1,如果设置了onTouchListener 且onTouch() return true 的话,也会有同样问题,就会出现lint提示

3.Activity的事件分发

Activity通过dispatchTouchEvent把触摸事件分发给其Window(唯一实现类PhoneWindow), PhoneWindow又通过superDispatchTouchEvent分发给其持有的DecorView,而DecorView是一个FrameLayout。这样就完成了Activity到ViewGroup的分发。 如果整个分发过程中的onTouchEvent都return false了,最终由activity的onTouchEvent(ev)消耗

public class Activity{
    public boolean dispatchTouchEvent(MotionEvent ev) {
        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
            onUserInteraction();
        }
        if (getWindow().superDispatchTouchEvent(ev)) {
            return true;
        }
        return onTouchEvent(ev);
    }
}

public abstract class Window {
	public abstract boolean superDispatchTouchEvent(MotionEvent event);
}

public class PhoneWindow extends Window{
	private DecorView mDecor;
    
	@Override
    public boolean superDispatchTouchEvent(MotionEvent event) {
        return mDecor.superDispatchTouchEvent(event);
    }
}

public class DecorView extends FrameLayout
    public boolean superDispatchTouchEvent(MotionEvent event) {
        return super.dispatchTouchEvent(event);
    }
}