为何子View可调用getParent().requestDisallowInterceptTouchEvent(true)?父拦截时如何执行?
子View调用
requestDisallowInterceptTouchEvent的执行逻辑解析 示例代码
@Override public boolean dispatchTouchEvent(MotionEvent ev) { // why this code can be executed. getParent().requestDisallowInterceptTouchEvent(true); return super.dispatchTouchEvent(ev); }
问题
getParent().requestDisallowInterceptTouchEvent(true)用于告知父View不要拦截触摸事件,但如果父View已经拦截了触摸事件,事件无法传递到子View,那么子View是如何执行该方法的?
这问题问到点子上了,咱们得从Android触摸事件的传递流程来拆解:
首先要明确一个核心规则:触摸事件的分发是从上到下,拦截是有阶段的。
- 当第一个触摸事件(
ACTION_DOWN)到来时,系统会从Activity的Window开始,把事件层层往下传递给子View。这个过程中,父View的onInterceptTouchEvent会被触发,如果它返回false(不拦截),事件就会落到子View的dispatchTouchEvent方法里——这时候你的这段代码就会执行,提前告诉父View:“后面的触摸事件(比如ACTION_MOVE、ACTION_UP)别拦我,我自己处理”。 - 那如果父View在
ACTION_DOWN阶段就返回true拦截了呢?那确实,子View的dispatchTouchEvent根本不会被调用,这段代码自然也跑不起来。但实际开发中,咱们用这个方法的场景,大多是父View不会在ACTION_DOWN时拦截,而是在后续的滑动事件中才可能抢事件——这时候子View已经在ACTION_DOWN阶段完成了“禁止拦截”的请求,父View就会遵守这个约定,不再拦截后续事件。
举个常见的场景:比如ScrollView嵌套RecyclerView时,RecyclerView会在ACTION_DOWN触发时调用这个方法,提前给ScrollView打“招呼”,这样用户在RecyclerView上滑动时,ScrollView就不会把事件抢过去自己滚动了。
最后再总结下:
- 只有父View没有拦截
ACTION_DOWN事件时,子View才有机会拿到事件并执行这段代码; - 如果父View一开始就拦截了
ACTION_DOWN,子View根本没机会执行这个方法,这种情况下这个调用也就不存在了。
内容的提问来源于stack exchange,提问作者Guo
相关产品推荐
相关产品推荐

