scrollview嵌套listview产生的滑动冲突(recyclerview)

2023-11-08

Android滑动冲突主要有两种方法:

1、外部拦截法

  1. public class ListScrollView extends ScrollView {  
  2.       
  3.     private ListView listView;  
  4.   
  5.     public ListScrollView(Context context, AttributeSet attrs) {  
  6.         super(context, attrs);  
  7.     }  
  8.   
  9.     public ListScrollView(Context context) {  
  10.         super(context);  
  11.     }  
  12.       
  13.     /** 
  14.      * 覆写onInterceptTouchEvent方法,点击操作发生在ListView的区域的时候, 
  15.      * 返回false让ScrollView的onTouchEvent接收不到MotionEvent,而是把Event传到下一级的控件中 
  16.      */  
  17.     @Override  
  18.     public boolean onInterceptTouchEvent(MotionEvent ev) {  
  19.         // TODO Auto-generated method stub  
  20.         if (listView != null && checkArea(listView, ev)) {  
  21.             return false;  
  22.         }  
  23.         return super.onInterceptTouchEvent(ev);  
  24.     }  
  25.       
  26.     /** 
  27.      *  测试view是否在点击范围内 
  28.      * @param locate 
  29.      * @param v 
  30.      * @return 
  31.      */  
  32.     private boolean checkArea(View v, MotionEvent event){  
  33.         float x = event.getRawX();  
  34.         float y = event.getRawY();  
  35.         int[] locate = new int[2];  
  36.         v.getLocationOnScreen(locate);  
  37.         int l = locate[0];  
  38.         int r = l + v.getWidth();  
  39.         int t = locate[1];  
  40.         int b = t + v.getHeight();  
  41.         if (l < x && x < r && t < y && y < b) {  
  42.             return true;  
  43.         }  
  44.         return false;  
  45.     }  
  46.   
  47.     public ListView getListView() {  
  48.         return listView;  
  49.     }  
  50.   
  51.     public void setListView(ListView listView) {  
  52.         this.listView = listView;  
  53.     }  
  54. }  

2、内部拦截法

listView.setOnTouchListener(new OnTouchListener() {
            
            public boolean onTouch(View v, MotionEvent event) {
                // TODO Auto-generated method stub
                listView.getParent().requestDisallowInterceptTouchEvent(true);
                return false;
            }
        });

同时要保证父布局不能拦截actiondown事件,否则所有事件都会交给父布局,即父布局重写 onInterceptTouchEvent为:

	@Override  
         public boolean onInterceptTouchEvent(MotionEvent e) {  
             int action = e.getAction();  
             if(action==MotionEvent.ACTION_DOWN) {  
             	return false;  
	     }
             return super.onInterceptTouchEvent(e);  
         }

参考Android开发艺术探索



彻底解决问题(完美版)

 
 

外层ScrollView,内嵌ListView,都是垂直方向。采用内部拦截法,实现ListView能滚动时则让ListView处理,当ListView滑到顶部或者底部不能滑动时让ScrollView处理

布局 上面有一段文本,中间是ListView,下面还有一段文本

<?xml version="1.0" encoding="utf-8"?>
<org.icegeneral.scroll.MyScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/sv"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="AAAAAAAAAA\nAAAAAAAAAA\nAAAAAAAAAA\nAAAAAAAAAA\nAAAAAAAAAA\nAAAAAAAAAA\nAAAAAAAAAA\nAAAAAAAAAA\nAAAAAAAAAA\nAAAAAAAAAA" />

        <org.icegeneral.scroll.MyListView
            android:id="@+id/lv"
            android:layout_width="match_parent"
            android:layout_height="500dp"
            android:background="#888888">

        </org.icegeneral.scroll.MyListView>

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="BBBBBBBBBB\nBBBBBBBBBB\nBBBBBBBBBB\nBBBBBBBBBB\nBBBBBBBBBB\nBBBBBBBBBB\nBBBBBBBBBB\nBBBBBBBBBB\nBBBBBBBBBB\nBBBBBBBBBB" />
    </LinearLayout>
</org.icegeneral.scroll.MyScrollView>

MyScrollView
ACTION_DOWN必须让给ListView,ListView才能收到ACTION_MOVE,ListView才能判断自己是否还能滚动
第二点要注意的是:因为ACTION_DOWN让给ListView,那么ACTION_DOWN就无法进入ScrollView的onTouchEvent, 但是ScrollView的滚动需要在ACTION_DOWN阶段做一些准备,所以主动调用了一次

public class MyScrollView extends ScrollView {

    public MyScrollView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
            onTouchEvent(ev);
            return false;
        }
        return true;
    }

}

MyListView

public class MyListView extends ListView {

    public MyListView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    private float lastY;

    @RequiresApi(api = Build.VERSION_CODES.KITKAT)
    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
            getParent().getParent().requestDisallowInterceptTouchEvent(true);
        } else if (ev.getAction() == MotionEvent.ACTION_MOVE) {
            if (lastY > ev.getY()) {
                // 如果是向上滑动,且不能滑动了,则让ScrollView处理
                if (!canScrollList(1)) {
                    getParent().getParent().requestDisallowInterceptTouchEvent(false);
                    return false;
                }
            } else if (ev.getY() > lastY) {
                // 如果是向下滑动,且不能滑动了,则让ScrollView处理
                if (!canScrollList(-1)) {
                    getParent().getParent().requestDisallowInterceptTouchEvent(false);
                    return false;
                }
            }
        }
        lastY = ev.getY();
        return super.dispatchTouchEvent(ev);
    }

}

Activity

protected void onCreate(Bundle savedInstanceState) {
    ....
    scrollView.smoothScrollTo(0, 0);
}

ACTION_DOWN的特殊性
解释下为什么ListView的ACTION_UP无需调用
getParent().getParent().requestDisallowInterceptTouchEvent(false)
来看下ViewGroup源码

@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
    ...
    boolean handled = false;
    if (onFilterTouchEventForSecurity(ev)) {
        final int action = ev.getAction();
        final int actionMasked = action & MotionEvent.ACTION_MASK;

        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 {
            intercepted = true;
        }
        ...
    }
    ...
}

private void resetTouchState() {
    clearTouchTargets();
    resetCancelNextUpFlag(this);
    mGroupFlags &= ~FLAG_DISALLOW_INTERCEPT; //移除FLAG_DISALLOW_INTERCEPT
    mNestedScrollAxes = SCROLL_AXIS_NONE;
}

所以如果是ACTION_DOWN,会调用resetTouchState(),移除FLAG_DISALLOW_INTERCEPT,所以ACTION_DOWN时,parent一定会进入onInterceptTouchEvent

其他
其实现在都用RecyclerView代替ListView,ScrollView嵌套RecyclerView时,对于手势已经支持得很好,不必自己处理冲突。这个在demo里也有写,做个对比

代码



作者:风风风筝
链接:http://www.jianshu.com/p/2b038cd9ac14
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

问题一:非常感谢博主,解决了我的问题,不过你在 ScrollView 的 onInterceptTouchEvent 的末尾 return true 会导致 ScrollView 里面的其他 View 无法再接收到 Event,所以还是应该改成 return super.onInterceptTouchEvent(ev) ,再次感谢

问题二:博主你好,如果你不在up里面去将request设置成false的话,scrollview上的点击事件就不能响应了

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------


http://blog.csdn.net/colinandroid/article/details/72770863

http://www.jianshu.com/p/2b038cd9ac14

http://www.cnblogs.com/1426837364qqcom/p/5388902.html

http://blog.csdn.net/lys701/article/details/8755373

http://blog.csdn.net/chaihuasong/article/details/17499799(有关requestDisallowInterceptTouchEvent

http://blog.csdn.net/Wisimer/article/details/49426653

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

scrollview嵌套listview产生的滑动冲突(recyclerview) 的相关文章

  • 如何为ScrollView放置固定图像背景?

    我应该想要滚动视图滚动 而不是背景中的图像 将图像添加到滚动视图框架之前的视图层次结构的较高位置
  • 如何对这个字符串进行子串化

    我想得到这个字符串的 4 个部分 String string 10 trillion 896 billion 45 million 56873 我需要的4个部分是 10万亿 8960亿 4500万 和 56873 我所做的是删除所有空格 然
  • React Native 从 JavaScript 代码内部访问 strings.xml

    有没有办法访问当前值android app src main res values strings xml从 JavaScript 代码内部 我想为每个构建放置不同的端点 URL 但我什至无法检测到反应本机代码内的构建类型 而不必求助于 D
  • android中向sqlite中插入大量数据

    目前 我必须一次向我的 Android 中插入超过 100 亿条数据 然而 内存不足的问题会使程序崩溃 sqlite 插入测试非常简单 只需使用 for 循环生成 sql 插入命令并通过 开始 和 提交 进行包装 private Array
  • SearchView过滤ListView

    我已经实现了搜索视图来过滤我的列表视图项目 当我输入任何文本时 它会过滤列表 但当我退出搜索视图时 它不会返回原始列表项 public class PlacesListAdapter extends ArrayAdapter
  • java.lang.NoClassDefFoundError:org.apache.batik.dom.svg.SVGDOMImplementation

    我在链接到我的 Android LibGDX 项目的 Apache Batik 库时遇到了奇怪的问题 但让我们从头开始 在 IntelliJ Idea 中我有一个项目 其中包含三个模块 Main Android 和 Desktop 我强调的
  • Android Activity 生命周期函数基础知识

    我正在测试这段代码 它显示活动所处的状态 public class Activity101Activity extends Activity String tag Lifecycle Called when the activity is
  • 当文本输入聚焦在 React Native for Android 的底部工作表上时,视图移出屏幕

    我正在使用图书馆 https github com osdnk react native reanimated bottom sheet https github com osdnk react native reanimated bott
  • 在 HTTPResponse Android 中跟踪重定向

    我需要遵循 HTTPost 给我的重定向 当我发出 HTTP post 并尝试读取响应时 我得到重定向页面 html 我怎样才能解决这个问题 代码 public void parseDoc final HttpParams params n
  • 无法访问 com.google.android.gms.internal.zzbfm 的 zzbfm 类文件未找到

    我正在将我的 Android 应用程序项目从GCM to FCM 为此 我使用 Android Studio 中的 Firebase 助手工具 并遵循 Google 开发人员指南中的说明 一切都很顺利 并将我的应用程序代码更改为FCM根据助
  • 如何使用 Cordova 获取当前安装的应用程序的版本?

    我已经找到了应用程序可用性插件 https github com ohh2ahh AppAvailability它主要检查用户是否在其设备上安装了某个应用程序 是否有可能获得应用程序的当前版本 开发者名称 重要 以及所有可能的信息 一般来说
  • Google 云端硬盘身份验证异常 - 需要许可吗? (v2)

    我一直在尝试将 Google Drive v2 添加到我的 Android 应用程序中 但无法获得授权 我收到 UserRecoverableAuthIOException 并显示消息 NeedPermission 我感觉 Google A
  • 我想实现下面的布局,按钮应该在屏幕底部,当惰性列被填充时,按钮不应该出去

    顶部有惰性列 惰性列下方有输入电话号码布局并从电话簿布局添加联系人 我希望当未添加联系人时此布局位于顶部 当我添加大量联系人时输入电话号码并添加电话簿布局中的联系人会随着惰性列滚动并移出屏幕 我不让他们走出屏幕 当接触较多时 它们必须粘在底
  • Android访问远程SQL数据库

    我可以直接从 Android 程序访问远程 SQL 数据库 在网络服务器上 吗 即简单地打开包含所有必需参数的连接 然后执行 SQL 查询 这是一个私人程序 不对公众开放 仅在指定的手机上可用 因此我不担心第三方获得数据库访问权限 如果是这
  • Android向menuItem添加子菜单,addSubMenu()在哪里?

    我想根据我的参数以编程方式将 OptionsMenu 内的子菜单添加到 menuItem 中 我检查了android sdk中的 MenuItem 没有addSubMenu 方法 尽管你可以找到 hasSubMenu 和 getSubMen
  • Android 套接字和 asynctask

    我即将开始制作一个应该充当 tcp 聊天客户端的应用程序 我一直在阅读和阅读 我得出的结论是最好 如果不需要 将我的套接字和异步任务中的阅读器 问题是我不确定从哪里开始 因为我是 Android 新手 这至少对我来说是一项艰巨的任务 但据我
  • 在activity_main.xml中注释

    我是安卓新手 据我所知 XML 中的注释与 HTML 中的注释相同 使用 形式 我想在 Android 项目的 Activity main xml 配置文件中写一些注释 但它给了我错误 值得注意的是 我使用的是 Eclipse 但目前 我直
  • 如何在Xamarin中删除ViewTreeObserver?

    假设我需要获取并设置视图的高度 在 Android 中 众所周知 只有在绘制视图之后才能获取视图高度 如果您使用 Java 有很多答案 最著名的方法之一如下 取自这个答案 https stackoverflow com a 24035591
  • 如何将 google+ 登录集成到我的 Android 应用程序中?

    大家好 实际上我需要通过我的应用程序从 google 登录人们 现在我阅读了 google 上的文档 其中指出 要允许用户登录 请将 Google Sign In 集成到您的应用中 初始化 GoogleApiClient 对象时 请求 PL
  • 节拍匹配算法

    我最近开始尝试创建一个移动应用程序 iOS Android 它将自动击败比赛 http en wikipedia org wiki Beatmatching http en wikipedia org wiki Beatmatching 两

随机推荐

  • Spring boot配置多个Redis数据源操作实例

    0 前言 平时都是使用本地环境的单Redis情况比较多 在集群环境的情况下连接多个Redis数据库是很正常的情况 最近小强遇到了一个问题 在SpringBoot项目中整合了两个Redis的操作实例 今天的数据产生后 需要完成离线数据和实时数
  • Mac上通过Pyenv安装python

    Mac上通过Pyenv安装python 前言 1 安装Pyenv 1 1A 使用Homebrew安装 1 1A 1 安装Homebrew 1 1A 2 安装pyenv 1 1B 使用git安装 1 2 配置环境变量 2 安装Python 3
  • 【ACCV2022】论文阅读笔记Lightweight Alpha Matting Network Using Distillation-Based Channel Pruning

    Lightweight Alpha Matting Network Using Distillation Based Channel Pruning 使用基于蒸馏通道裁剪的轻量Alpha抠图网络 https arxiv org pdf 22
  • 时间序列分析(11)

    上篇介绍的传递函数模型的假设是 会影响到 而不会影响到 因此称为外生变量 exogenous variable 如果和以及更多的变量之间能够相互影响 此时它们就是内生变量 endogenous variable 向量自回归模型 vector
  • 用Flutter自定义一个Button

    目录 简介 Widget StatelessWidget 案例 自定义Button StatefulWidget 案例 更新UI 效果图 总结 简介 Flutter是谷歌开发的跨平台UI工具包 通过一套代码库 我们能够构建出能运行在Andr
  • 围棋:三间低夹

    三间低夹 搜索结果 哔哩哔哩 Bilibili
  • (jsp和Servlet功能篇) session判断用户是否登入

    涉及文件 login do jsp和sessionCheck jsp和所有的jsp页面 1 在login do jsp登录成功的前面 加上 session setAttribute user model model里面放的是用户名和密码 u
  • 表达数量性状位点(eQTL)的概念及其相关分析原理

    表达数量性状位点 eQTL 的概念及其相关分析原理 表达数量性状位点 expression quantitative trait locus eQTL 是一类能够影响基因表达量的遗传位点 大部分都是单核苷酸多态性 SNP 具有一定的生物学意
  • PostgreSQL安装及简单使用

    一 PostgreSQL简介 1 什么是PostgreSQL PostgreSQL数据库是目前功能最强大的开源数据库 支持丰富的数据类型 如JSON何JSONB类型 数组类型 和自定义类型 而且它提供了丰富的接口 可以很容易地扩展它的功能
  • 【接口自动化测试】HTTP协议详解

    协议 简单理解 计算机与计算机之间的通讯语言就叫做协议 不同的计算机之间只有使用相同的协议才能通信 所以网络协议就是为计算机网络中进行数据交换而建立的规则 标准或约定的集合 OSI模型 1978年国际化标准组织提出了 开放系统互联网参考模型
  • 字节一面:如何实现单行/多行文本溢出的省略样式?

    前言 最近博主在字节面试中遇到这样一个面试题 这个问题也是前端面试的高频问题 作为一名前端开发工程师 css是我们的必备技能 文本溢出问题也是我们经常遇到的问题 我们不仅只是处理这种情况 还要考虑他的兼容性 博主在这给大家细细道来 作者简介
  • 设计模式与软件体系结构【期末全整理答案】

    题海茫茫 答案难觅 请点赞 关注我呦 期末试题基本出自这些题 请提前复制黏贴到word文档里 方便考试时直接查找 最好考前先浏览一遍 考试考到但不知道标准答案的题 如果有会的 麻烦在评论区写出答案 谢谢 1 代理模式的扩展是 2 简述状态模
  • Sublime Text 常用插件

    文章目录 ConvertToUTF8 BracketHighlighter Emmet JsFormat Compact Expand CSS Command Color Highlighter SublimeTmpl Alignment
  • jdk1.8安装教程及环境变量配置(含jdk8,11,13安装文件)

    目录 友情提醒 第一章 JVM JRE JDK介绍 第二章 下载和安装JDK 2 1 百度网盘直接下载免安装 2 2 官网下载安装JDK 需要收费 第三章 环境变量配置 3 1 windows环境变量配置 3 2 验证环境变量是否配置成功
  • 【基础】华为单臂路由技术配置实战

    1 实验拓扑 使用ENSP模拟器 版本V100R002C00 1 2 00 350 2 实验需求 1 PC1和PC3属于VLAN 10 2 PC2和PC4属于VLAN 20 3 全网互通 3 实验步骤 1 IP规划 PC1 192 168
  • 数据结构顺序表和单链表

    1 描述 设计整数顺序表的基本运算程序 并用相关数据进行测试 输入 顺序输入顺序表A的元素个数及各个元素 输出 第一行 创建顺序表A后 输出所有元素 第二行 删除第一个元素 输出删除后的所有元素 第三行 输出删除元素后顺序表的长度 第四行
  • 如何比较两个结构体是否相等

    今天定义了一个结构体来记录十一个球员的角色信息 后来在赋值 输出 比较时报错来 比如定义下面这样一个结构体 有什么效率高的办法比较他们是否相等呢 struct Student int age double height struct s1
  • 如何利用升压转换器产生双电源(产生正负电源)

    有时对于一些单电源供电应用我们需要将单电源转换成双电源以给像运算放大器这类芯片供电 我们常用的产生负电源的方法是使用DC DC转换模块或者反相DC DC转换器和电荷泵芯片 后两者是非隔离式 这里对以上三种产生负电源的方式做一些比较 DC D
  • Fully Attentional Network for Semantic Segmentation

    背景 非局部注意力使用一个简单的相似度矩阵 因此会造成attention miss 为了解决这个问题 提出了fully attentional network 同时进行位置和通道编码 本文主要解决在通道非局部中的位置问题 attention
  • scrollview嵌套listview产生的滑动冲突(recyclerview)

    Android滑动冲突主要有两种方法 1 外部拦截法 public class ListScrollView extends ScrollView private ListView listView public ListScrollVie