1.滑动冲突原因:

当有内外两层View同时可以滑动的时候,这个时候就会产生滑动冲突。

2.常见的冲突场景:

场景1:

场景2:

场景3:

4.解决方法种类:

(1)外部拦截法:

针对场景1,我们可以发现外部和内部的滑动方向不一样也就是说只要判断当前dy和dx的大小,如果dy>dx,那么当前就是竖直滑动,否则就是水平滑动。明确了这个我就就可以根据当前的手势开始拦截了。从view的事件分发中我们了解点击事件的分发顺序是 通过父布局分发,如果父布局没有拦截,即onInterceptTouchEvent返回false,才会传递给子View。所以我们就可以利用onInterceptTouchEvent()这个方法来进行事件的拦截。

  public boolean onInterceptTouchEvent(MotionEvent event) {
boolean intercepted = false;
int x = (int) event.getX();
int y = (int) event.getY(); switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: {
intercepted = false;
break;
}
case MotionEvent.ACTION_MOVE: {
if(父容器拦截的规则){
intercepted=true;
}else{
intercepted=false;
}
break;
}
case MotionEvent.ACTION_UP: {
intercepted = false;
break;
}
default:
break;
}
mLastXIntercept=x;
mLastYIntercept=y;
return intercepted;
}

上面的代码差多就是外部拦截的通用模板了,在onInterceptTouchEvent方法中,

首先是ACTION_DOWN这个事件,父容器必须返回false,即不拦截事件,因为一旦父容器拦截了ACTION_DOWN这个事件,那么后续的ACTION_MOVE和ACTION_UP事件将直接交给父容器处理,这个时候事件没法继续传递给子元素了;

然后是ACTION_MOVE这个事件,这个事件可以根据需要决定是否拦截,如果父容器需要拦截就返回true,否则返回false;

最后是ACTION_UP这个事件,这里必须返回false,因为这个事件本身也没有太多意义。

so场景一的外部拦截解决方法:

 public boolean onInterceptTouchEvent(MotionEvent event) {
boolean intercepted = false;
int x = (int) event.getX();
int y = (int) event.getY(); switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: {
intercepted = false;
break;
}
case MotionEvent.ACTION_MOVE: {
int deltaX=x-mLastXIntercept;
int deltaY=y=mLastYIntercept;
if(Math.abs(deltaX)>Math.abs(deltaY)){
intercepted=true;
}else{
intercepted=false;
}
break;
}
case MotionEvent.ACTION_UP: {
intercepted = false;
break;
}
default:
break;
}
mLastXIntercept=x;
mLastYIntercept=y;
return intercepted;
}

场景二的外部拦截方法:

 public boolean onInterceptTouchEvent(MotionEvent event) {
boolean intercepted = false;
int x = (int) event.getX();
int y = (int) event.getY(); switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: {
mLastYIntercept=y;
intercepted = super.onInterceptTouchEvent(event);
break;
}
case MotionEvent.ACTION_MOVE: {
if(listView.getFirstVisiblePosition()==0 &&y>mLastYIntercept){
intercepted=true;
}else if(listView.getLastVisiblePosition()==listView.getCount-1&&y <mLastYIntercept){
intercepted=false;
break;
}
intercepted = false;
break;
}
case MotionEvent.ACTION_UP: {
intercepted = false;
break;
}
default:
break;
}
mLastXIntercept=x;
mLastYIntercept=y;
return intercepted;
}

(2)内部拦截法

内部拦截法是指父容器不拦截任何事件,所有的事件都传递给子元素,如果子元素需要此事件就直接消耗掉,否则就交给父容器去处理

(android系统中,一次点击事件是从父view传递到子view中,每一层的view可以决定是否拦截并处理点击事件或者传递到下一层,如果子view不处理点击事件,则该事件会传递会父view,由父view去决定是否处理该点击事件。在子view可以通过设置此方法去告诉父view不要拦截并处理点击事件,父view应该接受这个请求直到此次点击事件结束)需要用到方法requestDisallowInterceptTouchEvent。

 内部拦截通用模板:

  

 public boolean onInterceptTouchEvent(MotionEvent event) {
int x = (int) event.getX();
int y = (int) event.getY(); switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: {
parent.requestDisallowInterceptTouchEvent(true); //父布局不要拦截此事件
break;
}
case MotionEvent.ACTION_MOVE: {
int deltaX=x-mLastXIntercept;
int deltaY=y=mLastYIntercept;
if(父容器需要拦截的事件){
parent.requestDisallowInterceptTouchEvent(false); //父布局需要要拦截此事件
}
break;
}
case MotionEvent.ACTION_UP: {
intercepted = false;
break;
}
default:
break;
}
mLastXIntercept=x;
mLastYIntercept=y;
return super.dispathTouchEvent(event);
}

so 场景二的内部拦截解决方法:

 //拦截除了Down事件以外的其他方法:
public boolean onInterceptTouchEvent(MotionEvent event) {
int x = (int) event.getX();
int y = (int) event.getY();
int action = event.getAction();
if(action == MotionEvent.ACTION_DOWN){
mLastXIntercept=x;
mLastYIntercept=y;
return super.dispathTouchEvent(event);
}else{
return true;
}
}

场景三建议使用内部拦截方法比较方便

View的滑动冲突和解决方案的更多相关文章

  1. 一个Demo带你彻底掌握View的滑动冲突

    本文已授权微信公众号:鸿洋(hongyangAndroid)在微信公众号平台原创首发. 近期在又一次学习Android自己定义View这一块的内容.遇到了平时开发中常常碰到的一个棘手问题:View的滑 ...

  2. view的滑动冲突解决方案

    一.常见的滑动冲突场景 1.外部滑动方向和内部滑动方向不一致 2.外部滑动方向和内部滑动方向一致 3.上面两种情况的嵌套 二.滑动冲突处理的原则 场景1的处理原则是:当用户左右滑动时,需要让外部的vi ...

  3. View的滑动冲突

    一.常见的滑动冲突 场景1:外部滑动和内部滑动不一致 场景2:外部滑动和内部滑动一致 场景3:上面两种情况的嵌套 二.滑动冲突的处理方法 场景一:根据水平滑动还是竖直滑动判断到底由谁来拦截事件. 场景 ...

  4. 自定义控件(视图)2期笔记13:View的滑动冲突之 内部拦截法

    1. 内部拦截法: 父容器不拦截事件,所有的事件全部都传递给子元素,如果子元素需要此事件就直接消耗掉,否则就交给父容器进行处理. 这种方法和Android中的事件分发机制不一样,需要配合request ...

  5. 自定义控件(视图)2期笔记12:View的滑动冲突之 外部拦截法

    1. 外部拦截法: 点击事件通过父容器拦截处理,如果父容器需要就拦截,不需要就不拦截. 这种方法比较符合事件分发机制.外部拦截法需要重写父容器的onInterceptTouchEvent方法,在内部做 ...

  6. 自定义控件(视图)2期笔记11:View的滑动冲突之 概述

    1. 引入: 滑动冲突可以说是日常开发中比较常见的一类问题,也是比较让人头疼的一类问题,尤其是在使用第三方框架的时候,两个原本完美的控件,组合在一起之后,忽然发现整个世界都不好了. 那到底是为什么会产 ...

  7. Android scrollview嵌套webview滑动冲突的解决方案

    在Android开发中有时我们需要在scrollview中嵌套webview这时你会发现这两者的滑动事件产生了冲突导致:webview很难被滑动,即使被滑动了一点也非常不顺畅.解决方案也比较简单只需要 ...

  8. Android开发——View滑动冲突解决方案

    0. 前言   我们在Android开发--事件分发机制详解中深入学习了事件分发机制,为我们解决Android开发中的滑动冲突问题做了初步准备.针对滑动冲突这里给出两种解决方案:外部拦截法和内部拦截法 ...

  9. (转载)Android滑动冲突的完美解决

    Android滑动冲突的完美解决 作者:softwindy_brother 字体:[增加 减小] 类型:转载 时间:2017-01-24我要评论 这篇文章主要为大家详细介绍了Android滑动冲突的完 ...

随机推荐

  1. Linux用户管理 (3)

    用户管理 1 用户添加 基本语法 useradd [选项] 用户名 添加一个用户: 注意事项 1)当用户创建成功后,会自动的创建和用户同名的家目录 2)也可以通过 useradd -d 指定目录 新的 ...

  2. Luogu P1039 侦探推理(模拟+枚举)

    P1039 侦探推理 题意 题目描述 明明同学最近迷上了侦探漫画<柯南>并沉醉于推理游戏之中,于是他召集了一群同学玩推理游戏.游戏的内容是这样的,明明的同学们先商量好由其中的一个人充当罪犯 ...

  3. 如何将数组2对象中的属性push进数组1的对象中去,组合成新的数组

  4. div contenteditable 重新编辑时focus光标定位到前面问题解决

    <div class="editdiv" id="edit" contenteditable="true">这是添加文字< ...

  5. Django如何自定义漂亮的404页面

    目录 在templates 中添加404.html 修改settings.py 在templates 中添加404.html <!DOCTYPE html PUBLIC "-//W3C ...

  6. LUOGU P1337 [JSOI2004]平衡点 / 吊打XXX(模拟退火)

    传送门 解题思路 学习了一下玄学算法--模拟退火,首先要求平衡处,也就是求势能最小的地方,就是求这个点到所有点的距离*重量最小.剩下的几乎是模拟退火的板子了. #include<iostream ...

  7. SpringBoot_01_SpringBoot入门

    1 Spring的优点分析 Spring是Java企业版(Java Enterprise Edition,JEE,也称J2EE)的轻量级代替品.无需开发重量级的Enterprise JavaBean( ...

  8. linux 软件 手动添加至桌面或启动栏

    1.创建软连接(也可以不用创建软连接,直接写绝对路径) sudo ln -s /opt/eclipse/eclipse /usr/bin/eclipse 2.创建desktop文件 sudo gedi ...

  9. 在Xsheel Linux上安装nodejs和npm

    最近window系统转向linux系统开发,linux系统的确适合程序员的开发. 作为前端安装了nodejs和npm,遇到了一些坑,赶紧记录下来 第一种安装方法:安装nodejs  : sudo  a ...

  10. Android之LinearLayout线性布局

    1.相关术语解释 orientation 子控件的排列方式,horizontal(水平)和vertical(垂直默认)两种方式! gravity 子控件的对齐方式,多个组合 layout_gravit ...