安卓开发过程中滑动冲突的情形主要有2类:
  • 父view与子view的滑动方向不同,如:父view左右滑动,子view上下滑动或相反(ViewPage里面嵌套ListView)。这种情形是比较简单的,只需要根据不同的滑动动作进行相应的拦截与处理即可。
  • 父view与子view的滑动方向相同,即,父view左右,子view也左右(ViewPage里面嵌套可以缩放、移动的ImageView)。这种情形需要根据具体情况来进行拦截处理,比如父View在出现子View滑动到边缘的情况才进行拦截处理。
滑动冲突解决策略的理论基础为安卓的事件分发机制,针对滑动冲突的解决策略有以下两种:
  • 一种是外部拦截法:即当事件满足滑动条件,通过父View的【onInterceptTouchEvent】方法对其进行拦截,拦截之后将直接进入父View的onTouchEvent进行事件消费,不会再传入下级view。
  • 二种是内部拦截法:即通过子View的【dispatchTouchEvent】方法接收到down事件,然后获取父View的requestDisallowInterceptTouchEvent方法禁止其onInterceptTouchEvent拦截,当满足父View滑动条件的时候才允许。这种方法需要父View不拦截down事件,因为拦截了down事件后所有子元素的触摸事件都会失效。
建议采用第一种方法,易于理解,不容易出错。

ViewPager里面嵌套ListView

实际测试后发现:原生根本就不会产生滑动冲突!
1、左右滑动(ViewPager处理触摸事件)

  • 当ACTION_DOWN = 0,按下动作时,先是父ViewPager判断是否拦截,由于此时父ViewPager还不能判断是否要进行拦截,所以onInterceptTouchEvent返回false,即不拦截,所以ACTION_DOWN事件可以(必须、务必、一定)传到子ListView。
  • 当ACTION_MOVE = 2,移动动作时,在父ViewPager尚未识别出此手势是左右滑动item的动作之前(一般是根据滑动的速度和累计距离判断),onInterceptTouchEvent同样也返回false,即同样不拦截,所以最初的这些ACTION_MOVE事件同样也可以传到ListView。
  • 一旦父ViewPager识别出此手势是左右滑动item的动作(比如水平方向移动了足够长的距离)
    • 1、那么onInterceptTouchEvent将返回true(红色框位置),即开始拦截,所以之后的这些ACTION_MOVE事件将无法传到ListView;
    • 2、并且父ViewPager会在此时传给子View一个ACTION_CANCEL= 3的"取消动作",当子ListView收到此事件后便取消了之前对此手势的预处理;
    • 3、并且此后父ViewPager将不再调用onInterceptTouchEvent判断是否需要拦截(因为它认为此后的事件都是自己需要的)
  • 此后所有的ACTION_MOVE、ACTION_UP=1事件都交由父ViewPager的onTouchEvent处理了。

2、上下滑动(ListView处理触摸事件)

可以发现,父ViewPager的onInterceptTouchEvent始终返回false,即从不会拦截触摸事件,所以上下滑动时的事件完全由ListView处理(这是最原始的状态)。
PS:
  • 父ViewPager的onInterceptTouchEvent在事件分发过程中(即dispatchTouchEvent方法调用时)并非是每次都会被调用的,一旦父ViewPager识别出此手势是自己需要的或不是自己需要的,之后都将不会再调用onInterceptTouchEvent判断是否需要拦截。
  • 所以判断判断某个View是否拦截了手势,只需看其最后一次调用onInterceptTouchEvent时的返回值即可。
  • 并且,很容易理解,其最后一次调用之前调用onInterceptTouchEvent时的返回值肯定都是false。

ListView里面嵌套ViewPager

1、上下滑动(ListView处理触摸事件)

情况和上面的一样

2、左右滑动(ViewPager处理触摸事件)
情况同样和上面一样

ScrollView里面嵌套ListView

1、当ScrollView的内容没有超出屏幕时(也即ScrollView不需要上下滑动),不会产生滑动冲突(也即内部的ListView能正常滑动),所有触摸事件都由ListView处理。
 
2、当ScrollView的内容超出屏幕时(也即ScrollView需要上下滑动),由于ListView也需要上下滑动,所以会产生滑动冲突(也即内部的ListView讲不能正常滑动),所有触摸事件都由ScrollView处理!

SV嵌套LV滑动冲突 之 外部拦截法

外部拦截法即:重写父容器的onInterceptTouchEvent方法,当自己需要的时候就拦截,否则不拦截。可以很容易理解,因为这和android自身的事件处理机制逻辑是一模一样的。
核心代码为:
    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        boolean intercepted = false;
        switch (ev.getAction()) {
        case MotionEvent.ACTION_DOWN://down事件肯定不能拦截,拦截了后面的就收不到了
            intercepted = false;
            break;
        case MotionEvent.ACTION_MOVE:
            if (true) intercepted = false;//如果确定拦截了,就去自己的onTouchEvent里处理拦截之后的操作即可
            break;
        case MotionEvent.ACTION_UP:
            //up事件我们一般都是返回false的,一般父容器都不会拦截他, 因为up是事件的最后一步,这里返回true也没啥意义。
            //唯一的意义就是,如果父元素把up拦截了,将导致子元素收不到up事件,那子元素就肯定没有onClick事件触发了,这里的小细节 要想明白
            intercepted = false;
            break;
        default:
            break;
        }
        return intercepted;

}

SV嵌套LV滑动冲突 之 内部拦截法

内部拦截法即:父容器不做处理,在子View中调用getParent().requestDisallowInterceptTouchEvent(true),作用是:告诉父view,我的触摸事件由我自行处理,不要阻碍我
不过前提是:要保证父亲容器不能拦截down事件。

核心代码为:

    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            break;
        case MotionEvent.ACTION_MOVE:
            //这里指定在什么条件下,才会要求父View把触摸事件交给自己处理。注意这里是调用的【getParent().getParent()】
            if (true) getParent().getParent().requestDisallowInterceptTouchEvent(true);//这句话的作用是告诉父view,我的触摸事件由我自行处理,不要阻碍我
            break;
        case MotionEvent.ACTION_UP:
            getParent().getParent().requestDisallowInterceptTouchEvent(false);//个人感觉这行代码没啥用,因为父view本来就不会拦截
            break;
        }
        return super.dispatchTouchEvent(event);

}

附件列表

【滑动冲突】常见情形及解决方案相关推荐

  1. Android View的事件分发机制和滑动冲突解决方案

    这篇文章会先讲Android中View的事件分发机制,然后再介绍Android滑动冲突的形成原因并给出解决方案.因水平有限,讲的不会太过深入,只希望各位看了之后对事件分发机制的流程有个大概的概念,并且 ...

  2. Android滑动冲突的完美解决方案

    一.Android滑动冲突的完美解决方案 在Android开发中滑动冲突可以说是比较常见的一类问题,也是比较让人头疼的一类问题,两个原本完美的控件,组合在一起之后,忽然发现整个世界都不好了.滑动冲突主 ...

  3. 安卓基础知识之View篇(四):View 事件滑动冲突解决方案

    安卓基础知识系列旨在简明扼要地提供面试或工作中常用的基础知识,让对安卓还不太熟悉的小伙伴更快地入门.同时自己在工作中,也没法完全记住所有的基础细节,写这样的系列文章,可以让自己形成一个更完备的知识体系 ...

  4. 一种嵌套滑动冲突的解决方案

    非嵌套滑动 | 嵌套滑动 相比起非嵌套滑动的自定义分发事件的方案,嵌套滑动冲突有比较成熟的 Google 解决方案:NestedScrolling . 三层嵌套的滑动冲突 UI 层级如下: 最外层(底 ...

  5. android滑动冲突的解决方案

    Android 中解决滑动的方案有2种:外部拦截法 和内部拦截法. 滑动冲突也存在2种场景: 横竖滑动冲突.同向滑动冲突. 所以我就写了4个例子来学习如何解决滑动冲突的,这四个例子分别为: 外部拦截法 ...

  6. Android 系统(218)---Android的事件分发机制以及滑动冲突的解决

    Android的事件分发机制以及滑动冲突的解决 声明:  本文主要涉及VIew的事件分发与滑动冲突的解决,关于View的事件分发流程的部分内容参考自:  Android事件分发机制详解:史上最全面.最 ...

  7. android中view手势滑动冲突的两种解决方法

    android中view手势滑动冲突的解决方法,主要解决方法有两种,外部和内部拦截.有需要的可以参考下. Android手势事件的冲突跟点击事件的分发过程息息相关,由三个重要的方法来共同完成,分别是: ...

  8. 看完还不会解决滑动冲突?呵呵,我食屎!!

    安卓设备由于由于屏幕的限制,如果想要在有限的屏幕中展示更多的内容,列表和弹窗就是一种非常好的解决方案,列表尤其是华滑动列表.咱们在日常的开发当中,使用最多的就要属滑动列表了,同样当滑动冲突也是我们日常 ...

  9. Android WebView与ViewPager的滑动冲突分析

    前言 如题所述,我使用的架构是ViewPager+Fragment+WebView进行开发的,由于WebView的html页面代码是第三方的,这里不好放出来,所以只能放一个大致的架构图,如图所示,Vi ...

  10. Flutter 28: 图解 ListView/GridView 混用时滑动冲突小尝试

    小菜在学习过程中会在一个 Page 页面同时用到 GridView 和 ListView 或多个 ListView,此时就会遇到常见的滑动冲突问题.小菜尝试了两种解决滑动冲突的方案,仅记录一下基本的使 ...

最新文章

  1. cadence16.6 中orcad导出网表时ERROR (ORCAP-5004)(win7 旗舰版32位)
  2. md5可以解密吗_Python训练营作业1:加密解密
  3. [html] DOM和BOM有什么区别?
  4. 奥鹏17计算机应用基础离线,奥鹏《计算机应用基础》离线
  5. ENVI二次开发时的注意事项
  6. python命令行进入帮助模式_Python 命令行之旅:深入 click 之选项篇
  7. java date eee_java将 Date原始格式EEE MMM dd HH:mm:ss Z yyyy转成指定格式
  8. Java基础教程【第五章:Java数组】
  9. 图网络模型原理详解(Graph Network)
  10. 火狐浏览器的hoxx附件还能用吗_Haspit
  11. Spring 事务和事务传播机制
  12. SQL Express
  13. mysql下载 补丁_mysql 官方补丁在哪里下载?
  14. Ubuntu18.04安装CAJ阅读器
  15. Loadrunner_集合点(rendezvous)
  16. 职业选择与职业规划【转载】
  17. 【BZOJ 1062】 1062: [NOI2008]糖果雨 (二维树状数组)**
  18. xshell用无线网远程连接linux失败_vnc远程控制软件怎么用,3个步骤教你vnc远程控制软件怎么用...
  19. 掩膜裁剪tif步骤_栅格数据批量掩膜(裁剪)
  20. Python利用百度地图获取两地距离 最详细过程和源代码

热门文章

  1. vue运行报错:Cannot find module 'webpack/bin/config-yargs'
  2. PHPMailer如何获取QQ邮箱授权码
  3. WORD中如何转换符号的全角半角
  4. SHELL使用sudo echo x 时提示权限不够,怎么办?
  5. 原来编译通过,现在编译不通过,怎么回事?
  6. 银河麒麟双击deb包无法安装
  7. 管理感悟:看清软件功能的“二八定律”
  8. Composite(组合)
  9. python 遍历字符串_python中如何实现遍历字符串的方法
  10. 超神学院暗物质计算机,超神学院之进击的赛亚人