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

时间:2022-10-20 22:50:38

在我前面的自定义裁剪窗口的代码中,我把裁剪的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的调用方法的更多相关文章

  1. Android 解决ScrollView下嵌套ListView进页面不在顶部的问题

    以下为整理: 方法1 刚开始还可以,后来再调试时就不行了. 为了解决scrollview和listview冲突  设置了listview的高度   结果进页面就不是在顶部了 . 解决方案1:Scrol ...

  2. Android -- 在ScrollView中嵌套ListView

    在做一个工程,这个工程的布局可以相当的复杂,最外面是ScrollView,在ScrollView里面有两个Listview,这下好了,布局出来了,放在机子上跑,卡得想死有木有,信息乱跑乱出现,表示非常 ...

  3. android 在一个scrollView里面嵌套一个需要滑动的控件(listView、gridView)

    package cn.via.dageeeOrderFood.widget; import android.content.Context; import android.graphics.Point ...

  4. android中ScrollView嵌套ListView或GridView显示位置问题

    Android中ScrollView中嵌套ListView或GridView时在开始进入界面时总是显示中间位置,开头的位置显示不出来.这种情况下只需要在ScrollView的父控件中添加以下两行代码即 ...

  5. Android 在ListView中嵌套ListView的事件处理

    前天在工作中遇到在ListView中的Item需要用ListView来展现处理后的内容,然后就遇到了一个很头疼的问题,作为Item的ListView没法进行滑动,而且显示也不正常,只是显示几个子Ite ...

  6. 【Android】ScrollView+GridView 显示问题

    在使用Android的ScrollView里面嵌套GridView时,设置android:layout_height="wrap_content"属性,运行界面的效果不会出现全部数 ...

  7. ScrollView中嵌套ListView显示

    想要ScrollView中嵌套显示ListView 需要自定义ListView 并重写onMeasure方法 重新计算  heightMeasureSpec的高度 int newHeight = Me ...

  8. android之ScrollView里嵌套ListView(转)

    hi,大家好,研究完ScrollView嵌套ScrollView之后,本人突然又想研究ScrollView里嵌套ListView了. 如果还不知道ScrollView嵌套ScrollView是怎么实现 ...

  9. Android之ScrollView嵌套ListView冲突

    在ScrollView中嵌套使用ListView,ListView只会显示一行多一点.两者进行嵌套,即会发生冲突.由于ListView本身都继承于ScrollView,一旦在ScrollView中嵌套 ...

随机推荐

  1. C/C++面试知识点总结

    1.中缀,后缀,前缀表达式: 后缀表达式是波兰逻辑学家卢卡西维奇(Lukasiewicz)发明的一种表示表达式的方法.这种表示方式把运算符写在运算对象的后面,例如,把a+b写成ab+,所以也称为后缀式 ...

  2. java编程算法

    一.字符串相关操作 String s = " Hello java,hello android,hello OOP,HELLO String,hello JAVASE!"; Sys ...

  3. linux终端下 编译c语言程序

    linux终端下,编译C语言程序步骤为: 采用vi进行源代码编写,编写完成后,:wq存盘退出,如: vi test.c 在命令行下,运行gcc编译程序,生成执行码,如: gcc  -o test te ...

  4. 代码创建FlexibleSpaceBarButton(弹性空白)

    //1.创建toolbar左边的按钮,调用initWithTitle方法进行初始化 // UIBarButtonItem *extend = [[UIBarButtonItemalloc]initWi ...

  5. oracle--dba和表的备份与恢复

    数据库管理员 每个oracle数据库应该至少有一名数据库管理员(dba),对于一个小的数据库,一个dba就够了,但是对于一个大的数据库可能需要多个dba分别担负不同的管理职责,那么一个数据库管理员的主 ...

  6. Shell学习---Shell脚本的静态检查工具shellcheck

    Shell脚本的静态检查工具shellcheck ubuntu下 apt install shellcheck ,即可安装shellcheck.写完shell脚本,记得用它检查一下,能给你点建议的.要 ...

  7. linux brctl command not found

    [root@localhost ~]# brctl-bash: brctl: command not found 解决方法: [root@localhost ~]# yum install bridg ...

  8. CentOS7系列--1.2CentOS7基本设置

    CentOS7基本设置 1. 查看相关信息 1.1. 查看系统信息 1.1.1. 查看系统位数 方法1: [root@centos7 ~]# uname -a Linux centos7.smartm ...

  9. java中的==操作符和equals函数

    基本规则 “==”操作符的使用需要分成两种情况 判值类型相等 这一点很好理解,两个值类型代表的数值相等,则“==”表达式返回true “==”可以用与不同值类型的比较,语言会自动进行类型转换 判引用类 ...

  10. python基础之内置异常对象

    前言 什么叫异常?简单来说就是程序运行发生了预计结果之外的情况从而导致程序无法正常运行.而python解释器将一些常见的异常情况在它发生时打包成一个异常对象,我们可以通过捕捉这些异常对象从而进行处理, ...