说一下安卓的touch事件分发机制

先从事件的传递开始.

一个事件到达界面时, 它的入口是dispatchTouchEvent. 这个方法是视图处理事件的唯一接口, 所有到达视图的事件, 都必须经过这个方法.

简单地说, 系统接收到一个事件, 要丢到一个LinearLayout里面, 怎么办?
直接调这个dispatchTouchEvent, 接收返回的true或者false, 完了.后面的处理就和这个LinearLayout没关系了.

那就有人问了, 那onInterceptTouchEvent, onTouchEvent, onClickListenr, 或者这个LinearLayout里面的Button, 不是还没处理吗, 怎么就完了?

虽然外部只调用dispatchTouchEvent, 但是在这个方法内部, 它自己会根据一系列逻辑调用这些方法.

件在视图之间传递的顺序大概是这样的:

父容器的dispatchTouchEvent-->调用内部容器的dispatchTouchEvent-->调用基本控件的dispatchTouchEvent.
这里的容器就是ViewGroup, 控件就是各种View.

通过这样的传递, 一个复杂的组件对它的上层来说就变得统一了: 我不要去关心你里面有什么乱七八糟的基本控件, 怎么摆放, 怎么处理. 我分分钟几十万上下, 找一个小小的具体的Button我累不累? 反正我就把事件丢给你, 怎么处理你来决定.
同样他的下级也是这个思路, 把事件丢到更下一级, 最终传达到一个Button让它响应处理.

这就是责任链模式.

但是这样又产生一个问题: 如果父容器只能起一个传递的作用, 事件只能由子控件响应, 那我ScrollView怎么滑动? ViewPager怎么切换? 工作不能都压给最底层的员工吧, 总有些事情是我经理得自己干的吧, 比如做报表写工作计划泡前台调戏测试之类的..... 咳咳扯远了.

所以这里就需要有一个判断的方法. 一个事件来了, 我自己审核一下, 这个是我的职责, 那后续的事情我就揽下来, 不往下传了. 否则就继续往下传. 嘿嘿我真是太机智了.

这个判断的方法就是onInterceptTouchEvent.

说到这里, 要区分 "动作" 和 "事件" 的概念了.

动作就是用户的一个完整的操作, 比如一个点击, 一个滑动, 等等.
而事件就是MotionEvent了.
我们知道所有的事件MotionEvent其实都是瞬态的, 一个事件本身只代表这一瞬间是什么样子. 你无法从单个MotionEvent看出用户当前是滑动还是长按, 滑动了多远, 向左还是向右. 一个完整的滑动动作是由不断触发 ACTION_DOWN, ACTION_MOVE x N, ACTION_UP(或者CANCEL)来组成的. 这些ACTION_DOWN, ACTION_MOVE代表事件的类型(getAction()).

那么问题又来了.一个单独的瞬态的ACTION_MOVE, 我怎么知道这个事件是2秒前的那次DOWN还是5秒前的那次DOWN带着的? 我如何判断一个完整的动作处理完没有?

视图是通过getDownTime() 这个属性. 每个动作的一系列事件都有相同的downTime, 也就是DOWN事件的getEventTime这个方法所返回的时间.

所以, 一个完整的动作是由一组MotionEvent组成的, 他们拥有共同的downTime. 当视图接收到具有一个新的downTime的事件时, 它就认为, 之前的动作已经处理完毕了.

这一块基本很少有提到过, 平时也用不太上. 但是很重要.

这个方法的参数虽然是一个事件, 但它实际上拦截的是一个完整的动作. 这就意味着, 如果你在DOWN事件或者某一个MOVE事件返回了true(意味着告诉视图:"我要拦截了, 这个动作我来处理!"), 那之后的所有事件都不会再继续往子视图传递了,直到有一个新的动作开始!

到这里, 我们可以试图解释一下, 为什么当ViewPager放在ScrollView里面时, 左右滑动经常变得很困难的原因.(筒子们可以试着自己动手写一个Demo, 你会发现左右滑动切换会变得比在外面困难很多.)

原因就是ScrollView在接收到MOVE事件时, 会判断前后两次事件的y坐标之差, 超过一定阈值就会认为是上下滑动事件, 然后就无情地通过onInterceptTouchEvent接管掉了.
而且这个阈值特别小......

而我们在左右滑动的时候, 手指很难保证完全水平地动作. 稍微有一点角度就产生了Y值的变化, 然后ScrollView大爷的onInterceptTouchEvent就觉得"卧槽这是上下滑动事件啊劳资不能不管啊!!!!".然后果断返回true.
于是可怜的ViewPager再也没接收到后续的事件, 也就切换不了了.

时间: 2024-10-07 10:37:33

说一下安卓的touch事件分发机制的相关文章

从Listview与Button点击事件冲突看安卓点击事件分发机制

题目有点长.其实实现Listview的时候大家都可能会碰到这样的一个问题,那就是Listview的OnItemClickListener点击事件与Button(或者checkbox)的touch(或者click)事件冲突的问题. 声明一下,非常感谢郭大师的这篇blog: http://blog.csdn.net/guolin_blog/article/details/9097463 原理参考了这篇blog,事实上也是本人功力不够不能阅读源码的缺陷啊. 下面说下自己的解决步骤: 1)首先先set一

安卓中的事件分发机制源码解析

安卓中的事件分发机制主要涉及到两类控件,一类是容器类控件ViewGroup,如常用的布局控件,另一类是显示类控件,即该控件中不能用来容纳其它控件,它只能用来显示一些资源内容,如Button,ImageView等控件.暂且称前一类控件为ViewGroup类控件(尽管ViewGroup本身也是一个View),后者为View类控件. 安卓中的事件分发机制主要涉及到dispatchTouchEvent(MotionEvent ev).onInterceptTouchEvent(MotionEvent e

Android的Touch事件分发机制简单探析

前言 Android中关于触摸事件的分发传递是一个很值得研究的东西.曾不见你引入了一个ListView的滑动功能,ListView就不听你手指的指唤来滚动了:也不知道为啥Button设置了onClick和onTouch,其中谁会先响应:或许你会问onTouch和onTouchEvent有什么区别,又该如何使用?这里一切的一切,只要你了解了事件分发机制,你会发现,解释这都不是事儿! 相关Touch事件的方法 1.public boolean dispatchTouchEvent(MotionEve

Android 源码解析View的touch事件分发机制

概述 本篇主要分析的是touch事件的分发机制,网上关于这个知识点的分析文章非常多.但是还是想通过结合自身的总结,来加深自己的理解.对于事件分发机制,我将使用两篇文章对其进行分析,一篇是针对View的事件分发机制解析,一篇是针对ViewGroup的事件分发机制解析.本片是对View的事件分发机制进行解析,主要采用案例结合源码的方式来进行分析. 前言 在分析事件分发机制之前,我们先来学习一下基本的知识点,以便后面的理解. View中有两个关键方法参与到Touch事件分发 dispatchTouch

Android开发之Touch事件分发机制

原地址http://www.cnblogs.com/linjzong/p/4191891.html Touch事件分发中只有两个主角:ViewGroup和View.Activity的Touch事件事实上是调用它内部的ViewGroup的Touch事件,可以直接当成ViewGroup处理. View在ViewGroup内,ViewGroup也可以在其他ViewGroup内,这时候把内部的ViewGroup当成View来分析. ViewGroup的相关事件有三个:onInterceptTouchEv

Android Touch事件分发机制学习

Android  事件分发机制 ViewGroup dispatchTouchEvent 返回true dispatchTouchEvent: Activity ACTION_DOWN MyrelativeLayout dispatchTouchEvent: ACTION_DOWN dispatchTouchEvent: Activity ACTION_UP MyrelativeLayout dispatchTouchEvent: ACTION_UP ViewGroup自己在dispatchTo

Touch事件分发机制

Touch事件分发中只有两个主角:ViewGroup和View.Activity的Touch事件事实上是调用它内部的ViewGroup的Touch事件,可以直接当成ViewGroup处理. View在ViewGroup内,ViewGroup也可以在其他ViewGroup内,这时候把内部的ViewGroup当成View来分析. ViewGroup的相关事件有三个:onInterceptTouchEvent.dispatchTouchEvent.onTouchEvent.View的相关事件只有两个:

Android:30分钟弄明白Touch事件分发机制

转载: 原文地址  点击打开链接 http://www.cnblogs.com/linjzong/p/4191891.html PS: 对照原文, 添加了一些文字, 表达更清晰(对本人来说) ---------------------------------------------质朴的分割线--------------------------------------------- Touch事件分发中只有两个主角:ViewGroup和View.Activity的Touch事件事实上是调用它内部

android touch事件分发机制

转载请注明出处:http://blog.csdn.net/ZhouLi_CSDN/article/details/45878337 看了网上那么多的博客 ,对于android系统的事件处理仍然不是明白的特别透彻,或者一些博客讲解的总是有些歧义或者讲诉的不正确或者不全面.所以自己总结了一下事件的传递机制希望可以帮助到广大的朋友. 假设事件传送路径为A-B-C-D-E; 一个手势是由事件action_down开始和action_move等其它事件以及事件action_up结束的集合: 一个actio