[Android] (在ScrollView里嵌套view)重叠view里面的onTouchEvent的调用方法

在我前面的自定义裁剪窗口的代码中,我把裁剪的view放在了大的scrollview里,这样就出现了程序只能触发scrollview,无法操作我的裁剪窗口。所以我加了那篇博客下面最后两段代码。其实我遇到这个问题的时候是在一个scrollview里添加了一个Edittext,我限制了Edittext的高度,所以edittext里面的内容过多时会自己产生滚动条。但我怎么也无法触发edittext的滚动事件,后来查了资料就明白了。后来一直没对它做记录,现在对这个知识点做一个总结。

原文地址请保留http://www.cnblogs.com/rossoneri/p/3994662.html

老规矩,先推荐博客资料,毕竟从别人那学来的知识,好东西要分享:

[Android实例] [版主原创]ScrollView嵌套ScrollView

[Android实例] [版主原创]android之ScrollView里嵌套ListView

其实这俩是一个作者,好多人也转载这个(吐槽下那些只转载不留原文地址的,太恶心)。但讲的有点罗嗦了。。其实下面有更清楚的:

Android ScrollView嵌套ScrollView滚动的问题解决办法

这个是从老外那转来的,老外网站我这打不开了。。反正讲的很简单清楚:告诉你不建议嵌套scrollview,但嵌套了也没关系,再告诉你出现问题的原因,然后给你解决方案,就两行代码而已blabla。

最后就是理解原理的关键:解决问题代码方法的说明

android 事件处理机制之requestDisallowInterceptTouchEvent

一万个赞!

好了,如果上面的你看完了,也就基本弄明白了,到这里就可以结束了。

 

 

 

 


 

总结:

这种情况说简单点就是上层的view的onTouchEvent和下层view的onTouchEvent重叠了,系统无法判断你想activate哪个onTouchEvent,然后系统就很蛋疼,跑程序的时候上层动一下,下层动一下,结果哪一层都动不起来(还是有小幅度偏移的)。这就是view之间的事,不限于scrollview,listView,gridView,自定义view什么的,所以标题定的也有问题,说白了就是view的嵌套。但为了文章能被更多的搜索到,我就是不改标题(什么心态)。

“当有多个层级的View时,在父层级允许的情况下,这个action会一直向下传递直到遇到最深层的View。所以touch事件最先调用的是最底层View的onTouchEent”

注意,允许,怎么设置是否允许呢?另外运行程序的时候的确是明显的,下层view先动,上层view后动,估计默认下父层级都是允许把消息传到最下层的吧

“如果View的onTouchEvent接收到某个touch action并作了相应处理,最后有两种返回方式return true和return false;return true会告诉系统当前的View需要处理这次的touch事件,以后的系统发出的ACTION_MOVE,ACTION_UP还是需要继续监听并接收 的,而且这次的action已经被处理掉了,父层的View是不可能触发onTouchEvent了”

了解一下onTouchEvent的返回值的用途

所以每一个action最多只能有一个onTouchEvent接口返回true

多层(>2)情况需要考虑一下

“如果return false,便会通知系统,当前View不关心这一次的touch事件,此时这个action会传向父级,调用父级View的onTouchEvent。 但是这一次的touch事件之后发出的任何action,该View都不会再接受,onTouchEvent在这一次的touch事件中再也不会触发,也就是说一旦View返回false,那么之后的ACTION_MOVE,ACTION_UP等ACTION就不会在传入这个View,但是下一次 touch事件的action还是会传进来的。”

这里不太明白。代码里return是在最后一行,所以会先执行前面的ACTION_*吧,return true的话,aiction执行之后再返回true,上层不再响应event可以理解,但false的话,他应该都执行过了啊?再给上层执行?

看了下源码,view的源码里onTouchEvent有一个int型的flag,在action触发前会做个判断,但自己复写方法的话。。。我怎么觉得好奇怪。。再想想。。这里面原理多呢。。

 1 public boolean onTouchEvent(MotionEvent event) {
 2         final int viewFlags = mViewFlags;
 3 
 4         if ((viewFlags & ENABLED_MASK) == DISABLED) {
 5             if (event.getAction() == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) {
 6                 setPressed(false);
 7             }
 8             // A disabled view that is clickable still consumes the touch
 9             // events, it just doesn't respond to them.
10             return (((viewFlags & CLICKABLE) == CLICKABLE ||
11                     (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE));
12         }
13 
14         if (mTouchDelegate != null) {
15             if (mTouchDelegate.onTouchEvent(event)) {
16                 return true;
17             }
18         }
19 
20         if (((viewFlags & CLICKABLE) == CLICKABLE ||
21                 (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)) {
22             switch (event.getAction()) {
23                 case MotionEvent.ACTION_UP:
24                     ...
25                     break;
26 
27                 case MotionEvent.ACTION_DOWN:
28                     ...
29                     break;
30 
31                 case MotionEvent.ACTION_CANCEL:
32             ...
33                     break;
34 
35                 case MotionEvent.ACTION_MOVE:
36                     ...
37                     break;
38             }
39             return true;
40         }
41 
42         return false;
43     }

“在父层级允许的情况下。假设不改变父层级的dispatch方法,在系统调用底层onTouchEvent之前会先调用父View的onInterceptTouchEvent方法判断,父层View是不是要截获本次touch事件之后的action。”

看到这里,前面的疑惑有点头绪,再看源码 

明天画个流程图出来

 

“如果onInterceptTouchEvent返回了true,那么本次touch事件之后的所有action都不会再向深层的View传递,统统都会 传给负层View的onTouchEvent,就是说父层已经截获了这次touch事件,之后的action也不必询问 onInterceptTouchEvent,在这次的touch事件之后发出的action时onInterceptTouchEvent不会再次调 用,知道下一次touch事件的来临。如果onInterceptTouchEvent返回false,那么本次action将发送给更深层的View, 并且之后的每一次action都会询问父层的onInterceptTouchEvent需不需要截获本次touch事件。只有ViewGroup才有 onInterceptTouchEvent方法,因为一个普通的View肯定是位于最深层的View,touch事件能够传到这里已经是最后一站了,肯 定会调用View的onTouchEvent。”

这段大概看看吧,前面基本了解了。

“对于底层的View来说,有一种方法可以阻止父层的View截获touch事件,就是调用 getParent().requestDisallowInterceptTouchEvent(true);方法。一旦底层View收到touch的 action后调用这个方法那么父层View就不会再调用onInterceptTouchEvent了,也无法截获以后的action。”

最后的关键方法,就用这个方法即可实现功能~(但最好要先搞懂原理)

 

最后贴个最早发现这个问题的代码,scrollview里的edittext,touch子view就设置其属性true,touch父view就帮子view设置属性false即可~

 1     mEssay.setOnTouchListener(new View.OnTouchListener() {
 2 
 3             @Override
 4             public boolean onTouch(View v, MotionEvent event) {
 5                 // TODO Auto-generated method stub
 6                 v.getParent().requestDisallowInterceptTouchEvent(true);
 7                 return false;
 8             }
 9         });
10 
11         mScrollView.setOnTouchListener(new View.OnTouchListener() {
12 
13             @Override
14             public boolean onTouch(View v, MotionEvent event) {
15                 // TODO Auto-generated method stub
16                 mEssay.getParent().requestDisallowInterceptTouchEvent(false);
17                 return false;
18             }
19         });

 

转载于:https://www.cnblogs.com/rossoneri/p/3994662.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/376623.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

带点击事件的Spinner

最近有一个蛋疼的需求,在下拉框中,如果只有一个值,默认显示出来,有两个或者没有显示请选择,没有点击不弹框,但是要清空,两个点击开要移掉请选择字样的项 本来以为很简单,后来发现没有…

linux进程间通信快速入门【二】:共享内存编程(mmap、XSI、POSIX)

文章目录mmap内存共享映射XSI共享内存POSIX共享内存参考使用文件或管道进行进程间通信会有很多局限性,比如效率问题以及数据处理使用文件描述符而不如内存地址访问方便,于是多个进程以共享内存的方式进行通信就成了很自然要实现的IPC方案。LInux给我们提…

ROBOTS.TXT屏蔽笔记、代码、示例大全

自己网站的ROBOTS.TXT屏蔽的记录,以及一些代码和示例: 屏蔽后台目录,为了安全,做双层管理后台目录/a/xxxx/,蜘蛛屏蔽/a/,既不透露后台路径,也屏蔽蜘蛛爬后台目录 缓存,阻止蜘蛛爬静态…

五大主流浏览器 HTML5 和 CSS3 兼容性比较

转眼又已过去了一年,在这一年里,Firefox 和 Chrome 在拼升级,版本号不断飙升;IE10 随着 Windows 8 在去年10月底正式发布,在 JavaScript 性能和对 HTML5 和 CSS3 的支持方面让人眼前一亮。这篇文章给大家带来《五大主流…

Ubuntu下将Sublime Text设置为默认编辑器

转自将Sublime Text 2设置为默认编辑器 修改defaults.list 编辑/etc/gnome/default.list文件,将其中的所有gedit.desktop替换为sublime_text.desktop。 sublime_text.desktop在/opt/sublime_text目录下,使用ls -al *sublime*命令查看具体文件名。 转载于…

python获取最近N天工作日列表、节假日列表

# 获取最近两周工作日列表、节假日列表 import datetime import chinese_calendar import time import pandas as pd# 将时间戳转换成格式化日期 def timestamp_to_str(timestampNone, format%Y-%m-%d %H:%M:%S):if timestamp:time_tuple time.localtime(timestamp) # 把时间…

保存页面的浏览记录

我的设计思想是将用户的浏览记录保存到cookie里面,然后根据情况处理。cookie里面的数据格式是json格式,方便根据自己的需要添加或者修改属性。引用了3个js文件,下载地址如下。 https://github.com/carhartl/jquery-cookie/blob/master/jquery.cookie.js …

开窍小老虎,一步一个脚印之 初识汇编(一)

最近一直浸淫在计算机编程中无法自拔。哲学 认识论中讲过。人类的求知的过程是由两次飞跃。第一是从感性认识到理性认识;第二是从理性认识到实践。这段话对有些人是适用的。我就是其中的一名。在知乎上求助问题“学计算机要懂汇编吗?”,地下有…

python脚本 请求数量达到上限,http请求重试

由于在内网发送http请求同一个token会限制次数,所以很容易达到网关流量上限。 业务中使用了多线程并发,一个线程发起一次http请求,得到正确结果后返回。这里采用的策略是,如果解析出来达到流量上限,那么该线程休眠一段…

shell 字符串操作

string"abcABC123ABCabc" 字符串长度: echo ${#string} #15 echo expr length $string #15 索引 用法:expr index $string $substring expr index $string "ABC" #4 提取子串 用法:${string:position} echo ${string:3} #A…

Linux 之目录 -鸟哥的Linux私房菜

因为利用 Linux 来开发产品或 distributions 的社群/公司与个人实在太多了, 如果每个人都用自己的想 法来配置档案放置的目录,那么将可能造成很多管理上的困扰。 你能想象,你进入一个企业之后,所 接触到的 Linux 目录配置方法竟然跟你以前学的完全不同吗? 很难想象吧~所以,后来…

python脚本:向表中插入新数据,删除表中最旧的数据

一张表存储历史数据,最多存储HISTORY_TABLE_MAX_ROWS条数据,当表中数据未达到HISTORY_TABLE_MAX_ROWS,直接插入;如果达到的话需要保证插入新数据的时候将最旧的数据删除 这里使用先update最新数据,然后再重新update全表…

精通 VC++ 实效编程280例 - 02 菜单和光标

菜单和关闭时重要的 Windows 资源之一。SDK 中,用 HCURSOR 和 HMENU 分别表示菜单和光标的句柄。MFC 中,CMenu 类封装了菜单的功能。 23 动态添加和删除菜单项 添加菜单项可以调用 CMenu::AppendMenu 或 CMenu::InserMenu 函数,删除菜单项可以…

POJ 1860: Currency Exchange 【SPFA】

套汇问题,从源点做SPFA,如果有一个点入队次数大于v次(v表示点的个数)则图中存在负权回路,能够套汇,如果不存在负权回路,则判断下源点到自身的最长路是否大于自身,使用SPFA时松弛操作…

python脚本:判断字符是否为中文

# 判断字符是否为中文 def is_chinese(ch):if u\u4e00 < ch < u\u9fff:return Trueelse:return False

Android 广播 Broadcast学习

Android Broadcast 广播 进程内本地广播 如果你是在你的应用之内使用广播&#xff0c;即不需要跨进程&#xff0c;考虑使用LocalBroadcastManager &#xff0c;这样更有效率&#xff08;因为不需要跨进程通信&#xff09;&#xff0c;并且你不用考虑一些其他应用可以发送或接收…

python:将时间戳转换成格式化日期

import time # 将时间戳转换成格式化日期 def timestamp_to_str(timestampNone, format%Y-%m-%d %H:%M:%S):if timestamp:time_tuple time.localtime(timestamp) # 把时间戳转换成时间元祖result time.strftime(format, time_tuple) # 把时间元祖转换成格式化好的时间retur…

WebApp 里Meta标签大全

1.先说说mate标签里的viewport&#xff1a; viewport即可视区域&#xff0c;对于桌面浏览器而言&#xff0c;viewport指的就是除去所有工具栏、状态栏、滚动条等等之后用于看网页的区域。对于传统WEB页面来说&#xff0c;980的宽度在iphone上显示是很正常的&#xff0c;也是满屏…

python:封装CRUD操作

# 封装数据库操作 def SELECT(db, cursor, sql):try:# 执行SQL语句db.ping(reconnectTrue)cursor.execute(sql)# 获取所有记录列表results cursor.fetchall()logging.debug("select commit")except:logging.error(sql)logging.error("select 语句执行出错"…

我的osu游戏程序设计(oo)

osu是一款社区元素为主旨的音乐游戏,由澳大利亚人Dean Herbert (peppy)独立制作并运行. 游戏的方法简单,就是 1. 圈圈(Circle)&#xff1a;圈圈(Circle) 50。没打中显示X,并减少生命值。圈中序号的最后一个的300、100会显示为激300、喝100。2.滑条(Slider) : 在开始端点击按住不…