requestDisallowInterceptTouchEvent实现原理
来源:互联网 发布:赵本山支持女儿玩网络 编辑:程序博客网 时间:2024/05/16 02:49
我们为了让底部的控件处理事件,不被父控件拦截,一般我们会调用
v.getParent().requestDisallowInterceptTouchEvent(true);
来阻止父控件对事件的拦截,来看下它的实现原理。
首先明确下v.getParent()对于底部的View来说,得到的就是上层的父控件,也就是上层的ViewGroup,来看下ViewGroup的requestDisallowInterceptTouchEvent方法
@Override public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) { if (disallowIntercept == ((mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0)) { // We're already in this state, assume our ancestors are too return; } if (disallowIntercept) { mGroupFlags |= FLAG_DISALLOW_INTERCEPT; } else { mGroupFlags &= ~FLAG_DISALLOW_INTERCEPT; } // Pass it up to our parent if (mParent != null) { mParent.requestDisallowInterceptTouchEvent(disallowIntercept); } }
首先就是判断是否已经设置过,如果没有,则在mGroupFlags中添加FLAG_DISALLOW_INTERCEPT这个标记位,接着如果该控件还有父控件,则一层一层在往上传递。
也就是说调用该方法就是将其上层所有控件的mGroupFlags中添加上FLAG_DISALLOW_INTERCEPT标记位。
那是怎么起到让父控件不拦截事件呢,我们知道事件的分发主要由三个方法决定dispatchTouchEvent,onInterceptTouchEvent,onTouchEvent,我们看下ViewGroup的dispatchTouchEvent方法
public boolean dispatchTouchEvent(MotionEvent ev) { ...... if (actionMasked == MotionEvent.ACTION_DOWN) { cancelAndClearTouchTargets(ev); resetTouchState(); } // Check for interception. final boolean intercepted; if (actionMasked == MotionEvent.ACTION_DOWN || mFirstTouchTarget != null) { final boolean disallowIntercept = (mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0; if (!disallowIntercept) { intercepted = onInterceptTouchEvent(ev); ev.setAction(action); // restore action in case it was changed } else { intercepted = false; } } else { // There are no touch targets and this action is not an initial down // so this view group continues to intercept touches. intercepted = true; } ......}
首先看下resetTouchState方法
private void resetTouchState() { clearTouchTargets(); resetCancelNextUpFlag(this); mGroupFlags &= ~FLAG_DISALLOW_INTERCEPT; mNestedScrollAxes = SCROLL_AXIS_NONE; }
关注点就是mGroupFlags &= ~FLAG_DISALLOW_INTERCEPT;也就是说如果是事件的起点,即MotionEvent.ACTION_DOWN的话就将标记位清除
接着就是关键点,决定是否调用onInterceptTouchEvent方法
我们看到第一个if中的判断语句为
actionMasked == MotionEvent.ACTION_DOWN || mFirstTouchTarget != null
也就是说必须满足至少一个条件才有可能去执行onInterceptTouchEvent方法
1:事件为ACTION_DOWN事件
2:mFirstTouchTarget 不为空
我们看下mFirstTouchTarget 的说明
// First touch target in the linked list of touch targets. private TouchTarget mFirstTouchTarget;
就是说mFirstTouchTarget 代表这个ViewGroup下第一个处理了事件的控件
要么为ACTION_DOWN事件,要么底下的控件处理了控件,反言之,如果这个ViewGroup曾经把事件交给下面的View去处理,而下面的View没有处理的话,那么下次事件ViewGroup的intercepted就直接被赋值为true,即将事件拦截,自己处理,好吧,这个很重要,但是和我们的requestDisallowInterceptTouchEvent关系也是不大
接着看第二个if判断语句
final boolean disallowIntercept = (mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0;if (!disallowIntercept) { intercepted = onInterceptTouchEvent(ev); ev.setAction(action); // restore action in case it was changed} else { intercepted = false;}
disallowIntercept就是前面我们一直提到的标记位
如果disallowIntercept为false,也就是默认值,那么就会走正常的onInterceptTouchEvent去判断是否拦截,像RelativeLayout,LinearLayout这样的一般不需处理事件的ViewGroup一般都会返回false,事件还是会继续传递下去;但是像RecyclerView,ViewPager这些,他们往往会根据判断事件的具体情况,决定是否拦截,可能自己就将事件消费了
而如果disallowIntercept为true的话,即我们设置不允许父控件拦截事件,那么他的onInterceptTouchEvent方法就不会执行,intercepted直接设置为false,即不拦截事件,事件会传递给下层的View,当然了如果最终下面的View不争气,没有处理事件的话,那么根据我们上面说的,之后的事件在第一个if判断的时候就会决定事件不再往下传递了
- requestDisallowInterceptTouchEvent实现原理
- requestDisallowInterceptTouchEvent
- requestDisallowInterceptTouchEvent
- requestDisallowInterceptTouchEvent
- requestDisallowInterceptTouchEvent
- requestDisallowInterceptTouchEvent
- requestDisallowInterceptTouchEvent
- requestDisallowInterceptTouchEvent
- requestDisallowInterceptTouchEvent
- requestDisallowInterceptTouchEvent
- requestDisallowInterceptTouchEvent
- 【Android】requestDisallowInterceptTouchEvent
- Android requestDisallowInterceptTouchEvent
- requestDisallowInterceptTouchEvent---1
- requestDisallowInterceptTouchEvent---2
- requestDisallowInterceptTouchEvent方法
- android ViewParent requestDisallowInterceptTouchEvent 测试
- android requestDisallowInterceptTouchEvent的用途
- 网页版别踩白块
- Linux下文件的相关操作
- MyBatis Like语句使用方式
- theano,numpy tile函数
- 《机器学习实战》和Udacity的ML学习笔记之 支持向量机&kernel
- requestDisallowInterceptTouchEvent实现原理
- 生成唯一订单号
- 二进制中1的个数
- centOS服务器装tomcat
- Huawei mate7调试老掉线的问题
- Android studio导入项目.9图报错
- Linux下文件的属性
- poj 3155 Hard Life(01分数规划+最大流--最大密度子图)
- java基础-数据类型