[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触发前会做个判断,但自己复写方法的话。。。我怎么觉得好奇怪。。再想想。。这里面原理多呢。。
public boolean onTouchEvent(MotionEvent event) {
final int viewFlags = mViewFlags;
if ((viewFlags & ENABLED_MASK) == DISABLED) {
if (event.getAction() == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) {
setPressed(false);
}
// A disabled view that is clickable still consumes the touch
// events, it just doesn't respond to them.
return (((viewFlags & CLICKABLE) == CLICKABLE ||
(viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE));
}
if (mTouchDelegate != null) {
if (mTouchDelegate.onTouchEvent(event)) {
return true;
}
}
if (((viewFlags & CLICKABLE) == CLICKABLE ||
(viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)) {
switch (event.getAction()) {
case MotionEvent.ACTION_UP:
...
break;
case MotionEvent.ACTION_DOWN:
...
break;
case MotionEvent.ACTION_CANCEL:
...
break;
case MotionEvent.ACTION_MOVE:
...
break;
}
return true;
}
return false;
}
“在父层级允许的情况下。假设不改变父层级的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即可~
mEssay.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
v.getParent().requestDisallowInterceptTouchEvent(true);
return false;
}
});
mScrollView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
mEssay.getParent().requestDisallowInterceptTouchEvent(false);
return false;
}
});
[Android] (在ScrollView里嵌套view)重叠view里面的onTouchEvent的调用方法的更多相关文章
- Android 解决ScrollView下嵌套ListView进页面不在顶部的问题
以下为整理: 方法1 刚开始还可以,后来再调试时就不行了. 为了解决scrollview和listview冲突 设置了listview的高度 结果进页面就不是在顶部了 . 解决方案1:Scrol ...
- Android -- 在ScrollView中嵌套ListView
在做一个工程,这个工程的布局可以相当的复杂,最外面是ScrollView,在ScrollView里面有两个Listview,这下好了,布局出来了,放在机子上跑,卡得想死有木有,信息乱跑乱出现,表示非常 ...
- android 在一个scrollView里面嵌套一个需要滑动的控件(listView、gridView)
package cn.via.dageeeOrderFood.widget; import android.content.Context; import android.graphics.Point ...
- android中ScrollView嵌套ListView或GridView显示位置问题
Android中ScrollView中嵌套ListView或GridView时在开始进入界面时总是显示中间位置,开头的位置显示不出来.这种情况下只需要在ScrollView的父控件中添加以下两行代码即 ...
- Android 在ListView中嵌套ListView的事件处理
前天在工作中遇到在ListView中的Item需要用ListView来展现处理后的内容,然后就遇到了一个很头疼的问题,作为Item的ListView没法进行滑动,而且显示也不正常,只是显示几个子Ite ...
- 【Android】ScrollView+GridView 显示问题
在使用Android的ScrollView里面嵌套GridView时,设置android:layout_height="wrap_content"属性,运行界面的效果不会出现全部数 ...
- ScrollView中嵌套ListView显示
想要ScrollView中嵌套显示ListView 需要自定义ListView 并重写onMeasure方法 重新计算 heightMeasureSpec的高度 int newHeight = Me ...
- android之ScrollView里嵌套ListView(转)
hi,大家好,研究完ScrollView嵌套ScrollView之后,本人突然又想研究ScrollView里嵌套ListView了. 如果还不知道ScrollView嵌套ScrollView是怎么实现 ...
- Android之ScrollView嵌套ListView冲突
在ScrollView中嵌套使用ListView,ListView只会显示一行多一点.两者进行嵌套,即会发生冲突.由于ListView本身都继承于ScrollView,一旦在ScrollView中嵌套 ...
随机推荐
- / | \ # $ ^ & *这些符号怎么读
供参考: /: slash或forward slash 英 [slæʃ] |: vertical bar或pipe #: number sign或pound sign \: backslash 英 [ ...
- 一眼看穿flatMap和map的区别
背景 map和flatmap,从字面意思或者官网介绍,可能会给一些人在理解上造成困扰[包括本人],所以今天专门花时间来分析,现整理如下: 首先做一下名词解释---------------------- ...
- nginx lua集成
版本说明: linux: 1.8.1 luajit:2.0.2(不要使用标准lua,应当使用luajit, 后者的效率比前者高很多) ngx_devel_kit: 0.2.18 lua-nginx-m ...
- 搭建Golang开发环境
Go语言是谷歌 2009 年首次推出并在 2012 年正式发布的一种全新的编程语言,可以在不损失应用程序性能的情况下降低代码的复杂性.谷歌首席软件工程师罗布派克(Rob Pike)说:我们之所以开发 ...
- JavaScript -- Window-Move,Print
-----035-Window-Move.html----- <!DOCTYPE html> <html> <head> <meta http-equiv=& ...
- centOS 6.5上安装mysql5.7压缩版
mysql-5.7.10-linux-glibc2.5-i686.tar.gz是目前最新版,二进制发布包,适合各种32为版本的发型版Linux,由于只有一个包,解压后配配就行,很方便,比较符合我的风格 ...
- Tensorflow运用RNN注意事项
一.学习单步的RNN:RNNCell 如果要学习TensorFlow中的RNN,第一站应该就是去了解“RNNCell”,它是TensorFlow中实现RNN的基本单元,每个RNNCell都有一个cal ...
- jar包运行main程序
当把java项目打包成jar后,如何运行main函数呢? 第一种:指定运行main类: 1 java -cp test.jar com.hk.app.Application 第二种:在MANIFEST ...
- “网红架构师”解决你的Ceph 运维难题
欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由Tstack发表于云+社区专栏 本文为长篇连续剧,将分多个篇幅发表,主要介绍了从动手部署环境到后期运营故障处理过程中常见的问题,内容由 ...
- 【K8S学习笔记】Part1:使用端口转发访问集群内的应用
本文介绍如何使用kubectl port-forward命令连接K8S集群中运行的Redis服务.这种连接方式有助于数据库的调试工作. 注意:本文针对K8S的版本号为v1.9,其他版本可能会有少许不同 ...