View的事件传递机制是从activity到window再到ViewGroup逐级传递到最底层的View的。具体是会调用View的dispatchTouchEvent方法,里面又分为两个步骤。首先是onIntercpetTouchEvent,判断是否会拦截这个事件,不拦截的话会接着往子View传递,拦截的话则会调用当前View的onTouchEvent方法。
在View的dispatchTouchEvent是否拦截的判断中,有这样一段代码,会判断不允许拦截事件(FLAG_DISALLOW_INTERCEPT)是否被设置,这是在requestDisallowInterceptTouchEvent中设置的,如果设置了这个标志位为true,则会判断为不允许拦截事件,intercepted会为false,让事件能够传递到下一级.
而我对于requestDisallowInterceptTouchEvent的方法有两个问题
- 为什么在requestDisallowInterceptTouchEvent方法中只要当前View的标志位被置为true之后就不用再往上传递了,从代码来看是需要逐级往上传递的
- 在recyclerView的onIntercpetTouchEvent方法中如果写的是getParent().requestDisallowInterceptTouchEvent(true),则能够让recyclerView正常拦截到事件,而调用的如果是requestDisallowInterceptTouchEvent(true)则会导致事件丢失,根据requestDisallowInterceptTouchEvent会逐级往上设置,那么问题在哪呢
第一个问题:
ViewGroup的FLAG_DISALLOW_INTERCEPT标志只能够通过requestDisallowInterceptTouchEvent方法设置,因此一旦判断当前View的标志位被设置过,则可以判断往上的所有View都已经走过一遍设置的代码了,因此不需要再来一遍
第二个问题:
getParent().requestDisallowInterceptTouchEvent(true)设置是从当前View的父View开始生效的,当前View并没有设置,因此当前View才可以拦截事件,一旦调用的是requestDisallowInterceptTouchEvent(true)方法,会连当前View一起设置不允许拦截,每次事件都会往当前View的子View传递,直到清除标志位,此时事件又被当前View的父View拦截,因此会出现问题2的情况。