上一篇博客讨论了一下view中的事件分发,既然存在事件分发的过程,那么也就可能存在着冲突。常见的由以下三种形式的冲突。(外面叫做OuterViewGroup,包裹在里面的叫做InnerViewGroup)

  • OuterViewGroupInnerViewGroup 滑动方向不同。(比如 OuterViewGroup 左右滑动,InnerViewGroup上下滑动)。
  • OuterViewGroupInnerViewGroup 滑动方向相同。(比如两者都是上下滑动)。
  • 以上两种情况的混合。

当然,实际上我们需要解决的只是前两种的滑动冲突。(因为第三种只是前两种的混合)。

第一种OuterViewGroupInnerViewGroup 滑动方向不同,这种场景还是比较常见的。比如ViewPager嵌套FragmentFragment里面再嵌套一个需要滑动的东西比如ListView。但是我们在实际项目当中如果有这种组合场景,为什么没有冲突呢,这是因为ViewPager的代码中已经帮我们处理好这种冲突了。

那么如果我们当中有这种情况,又应该如何分析处理呢?假设OuterViewGroup需要左右滑动,InnerViewGroup需要上下滑动。当我们手指触摸(或点击)屏幕时,我们自己心里肯定知道我们的目的,是想让它左右滑动还是上下滑动,那么问题是程序怎么判断我们是左右滑动还是上下滑动呢。(首先要明白我们是不可能在屏幕上画出一条完全垂直或者完全平行的轨迹的)。程序常见的判断方式有几种。比较X轴或Y轴上滑动距离,比较X轴或Y轴上滑动速度。比较滑动的轨迹与坐标轴的夹角。而第一种判断两个方向的距离是比较简单常用的方式。

第二种OuterViewGroupInnerViewGroup 滑动方向相同。那么此时就没有办法根据事件或轨迹在X轴Y轴的速度距离等指标进行判断了。但是此时我们肯定能根据具体的业务场景来做判断(否则这业务或产品设计的不是扯淡嘛)。什么时候该OuterViewGroup滑动,什么时候该InnerViewGroup滑动,这些都要视具体业务场景判断。

针对第一种情况,OuterViewGroup左右滑动,InnerViewGroup上下滑动这种滑动冲突,我们常见的一种解决方案就是在 OuterViewGroup中(也就是父元素中),通过其onInterceptTouchEvent来控制事件应该是自己来处理呢,还是将事件分发给子view(也就是InnerViewGroup来处理)。

这种处理逻辑用伪代码来表示如下:

//记录我们上一个事件中滑动的距离,这是为了进行进一步的判断
int mLastInterceptX = 0;
int mLastInterceptY = 0; public boolean onInterceptTouchEvent(MotionEvent event){
boolean intercept = false;
int x = event.getX();
int y = event.getY(); switch(event.getAction){
case MotionEvent.ACTION_DOWN;
/**
* 要搞清楚,我们是不能拦截ACTION_DOWN事件的。
* 如果在一个事件序列当中,我们拦截了ACTION_DOWN,那么该序列中剩下的事件也会交给该View进行处理,
* 不会再调用 onInterceptTouchEvent()方法来询问是否拦截事件了。
*/
intercept = false;
break;
case MotionEvent.ACTION_MOVE;
//判断是否需要拦截处理事件
if (interceptCondition()){
intercept = true;
} else {
intercept = false;
}
break;
case MotionEvent.ACTION_UP;
//我们常用的onClickListener就是判断的ACTION_UP,所以这里也返回false。
//这样就不会影响 点击(包含长按)事件的处理。
intercept = false;
break;
default:
} mLastInterceptX = x;
mLastInterceptY = y; return intercept;
} //
/**
* 判断父元素即OuterViewGroup是否需要拦截处理事件。
* 常用的判断方式由几种,比如根据X轴Y轴的距离, 速度,夹角等
*/
public boolean interceptCondition(MotionEvent event){
//我们假设OuterViewGroup需要左右滑动,我们根据 X轴和Y轴的距离来判断。
int distanceX = Math.abs(mLastInterceptX - event.getX());
int distanceY = Math.abs(mLastInterceptY - event.getY());
if ( distanceX > distanceY){
return true;
} else {
return false;
}
}

以上就是关于解决滑动冲突的一种常见的方法,除此之外,还有一种方法,就是在InnerViewGroup当中使用requestDisallowTouchEvent来干涉父元素中的事件分发过程,不过这种方法我没有理解透彻,所以就不做阐述了。另外,其实相比之下,第一种方法也更加的简单易懂。

至于第一种方法的demo,参见:https://github.com/yaowen369/BlogDemo/tree/master/Android/AndroidBlogDemo/app/src/main/java/com/yaoxiaowen/android_blog_demo/dispatch_event/slide_conflict

处的代码

备注:本篇博客的内容,均是参考了 任玉刚 的《Android开发艺术探索》的相关章节。


作者:
www.yaoxiaowen.com

github:
https://github.com/yaowen369

欢迎对于本人的博客内容批评指点,如果问题,可评论或邮件(yaowen369@gmail.com)联系

<p >
欢迎转载,转载请注明出处.谢谢
</p> <script type="text/javascript">
function Curgo()
{
window.open(window.location.href);
}
</script>

Android View的事件冲突的更多相关文章

  1. Android View 的事件分发原理解析

    作为一名 Android 开发者,每天接触最多的就是 View 了.Android View 虽然不是四大组件,但其并不比四大组件的地位低.而 View 的核心知识点事件分发机制则是不少刚入门同学的拦 ...

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

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

  3. Android View 的事件体系

    android 系统虽然提供了很多基本的控件,如Button.TextView等,但是很多时候系统提供的view不能满足我们的需求,此时就需要我们根据自己的需求进行自定义控件.这些控件都是继承自Vie ...

  4. Android view 的事件分发机制

    1 事件的传递顺序是 Activity -> Window -> 顶层View touch 事件产生后,最先由 activity 的 dispatchTouchEvent 处理 /** * ...

  5. viewpager与子view的事件冲突解决

    问题: 对android的事件机制一直不怎么了解,最近android项目中运用viewpager+listview (就是viewpager的子view中嵌套了listview),出现了触摸手势冲突 ...

  6. Android View的事件分发

    如果接触android开发时间足够长的话,或多或少都会遇到各种各样事件冲突的问题,要想解决这类问题,对深入理解事件分发机制是很有必要的,接下来几天都会尽自己所能尽可能将这方面讲清楚.  View的事件 ...

  7. Android ListView焦点事件冲突问题与解决

    Android ListView对于单纯列表展示是很好用的,但是一旦牵扯到对listView进行操作就会遇到各种各样的问题.比如保存Checkbox状态与item复用的冲突.遇到可获取焦点的控件比如说 ...

  8. Android View的事件分发机制探索

    概述 Android事件传递机制也是Android系统中比较重要的一块,事件类型有很多种,这里主要讨论TouchEvent的事件在framework层的传递处理机制.因为对于App开发人员来说,理解f ...

  9. Android View的事件分发机制

    准备了一阵子,一直想写一篇事件分发的文章总结一下.这个知识点实在是太重要了. 一个应用的布局是丰富的,有TextView,ImageView,Button等.这些子View的外层还有ViewGroup ...

随机推荐

  1. LNMP1.3 一键配置环境,简单方便

    系统需求: CentOS/RHEL/Fedora/Debian/Ubuntu/Raspbian Linux系统 需要3GB以上硬盘剩余空间 需要128MB以上内存(如果为128MB的小内存VPS,Xe ...

  2. Java 代码学习之数组的初始化

    我们都很熟悉Java中的数组,它具有查询快,增删慢的特点.但是通常我们自认为很了解它的用法,却容易忽略一些小细节.今天通过一段代码来简单了解数组初始化中的一些我们容易忽略的地方. package da ...

  3. SpringBoot多数据源配置

    准备环境: jdk1.8 eclipse tomcat8.0 第一步:在配置文件添加如下信息: spring.datasource.primary.url=jdbc:mysql://localhost ...

  4. 3.python元组与列表

    Python的元组与列表类似,同样可通过索引访问,支持异构,任意嵌套.不同之处在于元组的元素不能修改.元组使用小括号,列表使用方括号. 创建元组 元组创建很简单,只需要在括号中添加元素,并使用逗号隔开 ...

  5. dma_alloc_coherent (建立一致性 DMA 映射函数)

    1.函数申明 /** * dma_alloc_coherent - allocate consistent memory for DMA * @dev: valid struct device poi ...

  6. jquery 自定义选择器

    // HTML 代码 <body> <div id="divid1" class="divclass">白色</div> & ...

  7. 【Sqlserver系列】【转载】事物与锁

    1   概述 本篇文章简要对事物与锁的分析比较详细,因此就转载了. 2   具体内容 并发可以定义为多个进程同时访问或修改共享数据的能力.处于活动状态而互不干涉的并发用户进程的数量越多,数据库系统的并 ...

  8. python3.5新增函数isclose的使用

    前言:python3.5的math模块新增一个isclose函数用来判断两个浮点数的值是否接近或相等,这是由于浮点数的计算总是存在一定的误差.下面谈一下用法: import math print(ma ...

  9. CS:APP3e 深入理解计算机系统_3e ShellLab(tsh)实验

    详细的题目要求和资源可以到 http://csapp.cs.cmu.edu/3e/labs.html 或者 http://www.cs.cmu.edu/~./213/schedule.html 获取. ...

  10. intellij idea svn使用一 导入、更新、提交、解决冲突

    大体上是转载,针对版本14有一些特殊的添加. 查看svn的资源库: 下面的多出了一个svn的窗口,在左边有加号可以添加一个svn的库 输入svn的地址,我用的是本地的测试,所以地址为svn://127 ...