Android事件分发的三个基本方法
- dispatchTouchEvent:事件分发
- onInterceptTouchEvent:事件拦截(只有ViewGroup中有)
- onTouchEvent:事件处理
其中onInterceptTouchEvent和onTouchEvent是在dispatchTouchEvent中调用。
分发过程
dispatchTouchEvent方法负责把事件分发给自己或其子元素。
事件传递给ViewGroup后,ViewGroup的dispatchTouchEvent会被调用,其中会调用自己的onInterceptTouchEvent拦截方法,onInterceptTouchEvent返回true表示自己拦截事件,接着调用自己的onTouchEvent。onInterceptTouchEvent返回false表示自己不拦截事件,接着调用子元素的dispatchTouchEvent,直到事件在子元素中被拦截。
dispatchTouchEvent的返回值是onTouchEvent的返回值或子元素的dispatchTouchEvent的返回值,表示是否被消费。
dispatchTouchEvent分发调用的顺序是从父向子依次遍历调用的。
消费过程
onTouchEvent处理调用的顺序则是从子向父依次回溯调用的。
几个事件接口方法的优先级高低顺序
onTouchListener >>> onTouchEvent >>> setOnLongClickListener >>> OnClickListerner
滑动冲突解决方式
- 外部拦截法 —— 重写父容器的onInterceptTouchEvent方法;在父容器的onInterceptTouchEvent方法中,首先ACTION_DOWN事件父容器必须返回false,即不拦截ACTION_DOWN事件,因为如果父容器拦截了ACTION_DOWN,后续的ACTION_MOVE/ACTION_UP都将会交给父容器处理;其次是ACTION_MOVE,根据需求决定是否要拦截;最后ACTION_UP事件,必须要返回false,即不拦截ACTION_UP事件。
- 内部拦截法 —— 所有事件都传递给子元素,如果子元素需要就消耗掉,不需要就交给父元素处理。需要子元素配合调用requestDisallowInterceptTouchEvent方法才能正常工作;父元素需要默认拦截除ACTION_DOWN以外的事件,这样子元素调用parent.requestDisallowInterceptTouchEvent(false)方法时,父元素才能继续拦截需要的事件。(ACTION_DOWN事件不受requestDisallowInterceptTouchEvent方法影响,如果父元素拦截ACTION_DOWN事件,那么所有事件都无法传递到子元素去)。