热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

dispatchTouchEvent事件分发浅析(七)requestDisallowInterceptTouchEvent

上一篇,我们大体理解了对应的ACTION_DOWN之后对应的ACTION_MOVE和ACTION_UP的简单过程当然,还分是否消费等具体代码可以见https:github.com2

上一篇,我们大体理解了对应的ACTION_DOWN 之后
对应的ACTION_MOVE 和 ACTION_UP 的简单过程
当然,还分是否消费等

具体代码可以见https://github.com/2954722256/demo_event

这篇,我们一起来看下简单了解下事件冲突
还有一个简单解决事件冲突的例子

requestDisallowInterceptTouchEvent方法说明

我们可以看看API
在android的sdk,对应的
XxxAndroidSdkDir/docs/reference/android/view/ViewGroup.html
(因为这里不是将ViewGroup,所以其他略)
我们可以 搜索 requestDisallowInterceptTouchEvent, 找到对应的方法

void requestDisallowInterceptTouchEvent(boolean disallowIntercept)
Called when a child does not want this parent and its ancestors to intercept touch events with onInterceptTouchEvent(MotionEvent).

大概就是说,当 子View 不想被 父View 拦截的时候,
就可以调用requestDisallowInterceptTouchEvent(MotionEvent)方法,
这样,可以放父View的 onInterceptTouchEvent(MotionEvent)失效
(当然,还有其他情况,现在暂时略)

dispatchTouchEvent, onInterceptTouchEvent, requestDisallowInterceptTouchEvent简单关系

前面我们有说过,onInterceptTouchEvent 方法,只有ViewGroup有,并且默认是return false的

**onInterceptTouchEvent **

public boolean onInterceptTouchEvent(MotionEvent ev) {
return false;
}

那我们来看看 dispatchTouchEvent 方法
(我们先贴一下源码,再一起看看)

前面其实有一些修改Flags值的地方,暂时略
...前面省略...
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;
}
......
if (!canceled && !intercepted) {
......
...后面省略...

这里我们可以看见,对应的判定,
都是和2个局部变量canceled 和 intercepted有关
canceled 先不考虑,
intercepted 是和 mGroupFlags & FLAG_DISALLOW_INTERCEPT 有关
这2个变量,取与来判断 !=0
换句话说,就是对应的二进制码, 有没有都为 1 的地方。

mGroupFlags & FLAG_DISALLOW_INTERCEPT 简单分析

因为上面 intercepted 是和 mGroupFlags & FLAG_DISALLOW_INTERCEPT 有关
我们只要跟踪这2个变量,就可以大体找到对应的情况了

我们可以发现,
mGroupFlags 和很多方法有关,方法中和很多二进制的变量有关,并且这些二进制码都不太一样, 比较复杂,只能暂时放一下
FLAG_DISALLOW_INTERCEPT 就比较简单点, 只和
dispatchTouchEvent
resetTouchState()
requestDisallowInterceptTouchEvent
这3个方法有关
(先忽略resetTouchState()这个方法,也就是上面说的别的情况, dispatchTouchEvent上面已经贴了相关的代码)
这里我们贴一下 requestDisallowInterceptTouchEvent 方法实现

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 = 0x80000;
这里是16进制的,16进制1位相当于2进制的4位,
8是2的3次方,也就是1000
后面4个0,换成2进制,也就是16个0
整体就是10000000000000000000, 也就是1后面19个0

我们可以发现,对应的16进制值对应位数上都是不同的2的次方数,换句话说,对应的2进制数值,对应的位的1值,是不会相同的
所以 mGroupFlags & FLAG_DISALLOW_INTERCEPT 判断的时候,只需要判断那个第20位的1,即可
而后面 mGroupFlags的取与,取非后的或, 都只会那个第20位的数字
(我们可以理解,这里 mGroupFlags , 就是很多Flag对应boolean值的集合,每一位就一个不同的Flag变量的boolean值容器思维上和 Bloom Filter 的实现理论相似

这里 requestDisallowInterceptTouchEvent 方法
其实,就是修改当前 mGroupFlags 对应 FLAG_DISALLOW_INTERCEPT 位上的boolean值,再如果有 父View,修改父View的 mGroupFlags 值

如果为true,则会执行后面的方法,修改 父View对应的 mGroupFlags 值

最后,我们回到 上面贴的 dispatchTouchEvent 方法中,
判断是否走onInterceptTouchEvent(ev)的地方
如果 disallowIntercept 为 false,就会走
再看下 disallowIntercept 的判断

final boolean disallowIntercept = (mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0;

这个地方,如果 mGroupFlags 对应位上是1, 就为true,就不会走

也就是 requestDisallowInterceptTouchEvent 设置 true,
就不会走 onInterceptTouchEvent(ev) 方法

ScrollView 与 WebView 的冲突

我们有的时候会遇到这种情况,
整个是 ScrollView ,内部有一个 WebView ,还有其他的一些 子View
这时候,WebView 显示不全
但是, 滑动的时候, 又会触发外面 ScrollView的上下滚动,
于是 内部的WebView就看不全了

《dispatchTouchEvent事件分发浅析(七)requestDisallowInterceptTouchEvent》 Paste_Image.png

我们来看一下 ScrollView 的 onInterceptTouchEvent(MotionEvent ev) 方法

final int action = ev.getAction();
if ((action == MotionEvent.ACTION_MOVE) && (mIsBeingDragged)) {
return true;
}
...后面省略...

换句话说,只要是 MotionEvent.ACTION_MOVE, 后面都不用看, 就会被拦截
那内部的 子View的滑动,肯定不会被监听到了

我们在搜索下 WebView
里面完全没有 requestDisallowInterceptTouchEvent 相关方法的调用

所以, ScrollView 中套用 WebView 肯定会有这样的问题

简单解决ScrollView 与 WebView 的冲突

根据上面的思路, 我们只需要 Override对应的
onInterceptTouchEvent(MotionEvent ev) 方法
调用 requestDisallowInterceptTouchEvent(true); 即可

经检验, 是可以的
(对应的代码,见上面的github地址,在 disallowintercept 的Module中)

下一篇我们可以了解
dispatchTouchEvent事件分发浅析(八)简单解决ScrollView 与 WebView 的冲突


推荐阅读
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • 自动轮播,反转播放的ViewPagerAdapter的使用方法和效果展示
    本文介绍了如何使用自动轮播、反转播放的ViewPagerAdapter,并展示了其效果。该ViewPagerAdapter支持无限循环、触摸暂停、切换缩放等功能。同时提供了使用GIF.gif的示例和github地址。通过LoopFragmentPagerAdapter类的getActualCount、getActualItem和getActualPagerTitle方法可以实现自定义的循环效果和标题展示。 ... [详细]
  • 本文介绍了Android 7的学习笔记总结,包括最新的移动架构视频、大厂安卓面试真题和项目实战源码讲义。同时还分享了开源的完整内容,并提醒读者在使用FileProvider适配时要注意不同模块的AndroidManfiest.xml中配置的xml文件名必须不同,否则会出现问题。 ... [详细]
  • 本文介绍了Cocos2dx学习笔记中的更新函数scheduleUpdate、进度计时器CCProgressTo和滚动视图CCScrollView的用法。详细介绍了scheduleUpdate函数的作用和使用方法,以及schedule函数的区别。同时,还提供了相关的代码示例。 ... [详细]
  • 在Docker中,将主机目录挂载到容器中作为volume使用时,常常会遇到文件权限问题。这是因为容器内外的UID不同所导致的。本文介绍了解决这个问题的方法,包括使用gosu和suexec工具以及在Dockerfile中配置volume的权限。通过这些方法,可以避免在使用Docker时出现无写权限的情况。 ... [详细]
  • 目录实现效果:实现环境实现方法一:基本思路主要代码JavaScript代码总结方法二主要代码总结方法三基本思路主要代码JavaScriptHTML总结实 ... [详细]
  • ZSI.generate.Wsdl2PythonError: unsupported local simpleType restriction ... [详细]
  • FeatureRequestIsyourfeaturerequestrelatedtoaproblem?Please ... [详细]
  • 闭包一直是Java社区中争论不断的话题,很多语言都支持闭包这个语言特性,闭包定义了一个依赖于外部环境的自由变量的函数,这个函数能够访问外部环境的变量。本文以JavaScript的一个闭包为例,介绍了闭包的定义和特性。 ... [详细]
  • ScrollView嵌套Collectionview无痕衔接四向滚动,支持自定义TitleView
    本文介绍了如何实现ScrollView嵌套Collectionview无痕衔接四向滚动,并支持自定义TitleView。通过使用MainScrollView作为最底层,headView作为上部分,TitleView作为中间部分,Collectionview作为下面部分,实现了滚动效果。同时还介绍了使用runtime拦截_notifyDidScroll方法来实现滚动代理的方法。具体实现代码可以在github地址中找到。 ... [详细]
  • 十大经典排序算法动图演示+Python实现
    本文介绍了十大经典排序算法的原理、演示和Python实现。排序算法分为内部排序和外部排序,常见的内部排序算法有插入排序、希尔排序、选择排序、冒泡排序、归并排序、快速排序、堆排序、基数排序等。文章还解释了时间复杂度和稳定性的概念,并提供了相关的名词解释。 ... [详细]
  • 本文介绍了如何在Azure应用服务实例上获取.NetCore 3.0+的支持。作者分享了自己在将代码升级为使用.NET Core 3.0时遇到的问题,并提供了解决方法。文章还介绍了在部署过程中使用Kudu构建的方法,并指出了可能出现的错误。此外,还介绍了开发者应用服务计划和免费产品应用服务计划在不同地区的运行情况。最后,文章指出了当前的.NET SDK不支持目标为.NET Core 3.0的问题,并提供了解决方案。 ... [详细]
  • 本文详细介绍了Android中的坐标系以及与View相关的方法。首先介绍了Android坐标系和视图坐标系的概念,并通过图示进行了解释。接着提到了View的大小可以超过手机屏幕,并且只有在手机屏幕内才能看到。最后,作者表示将在后续文章中继续探讨与View相关的内容。 ... [详细]
  • Ihaveaworkfolderdirectory.我有一个工作文件夹目录。holderDir.glob(*)>holder[ProjectOne, ... [详细]
  • 工作经验谈之-让百度地图API调用数据库内容 及详解
    这段时间,所在项目中要用到的一个模块,就是让数据库中的内容在百度地图上展现出来,如经纬度。主要实现以下几点功能:1.读取数据库中的经纬度值在百度上标注出来。2.点击标注弹出对应信息。3 ... [详细]
author-avatar
吴台吉国瑋智仁
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有