参考博客:即于下面博客演变出自己的理解

【透镜系列】看穿 > 触摸事件分发 > - 掘金

Android事件分发机制_open-Xu的博客-CSDN博客

郭霖

Android事件分发机制完全解析,带你从源码的角度彻底理解(上)_guolin的博客-CSDN博客

Android事件分发机制完全解析,带你从源码的角度彻底理解(下)_guolin的博客-CSDN博客_android 事件分发机制 郭霖

事件分发机制:整体上遵循递归原则,递是指事件分发传递从Activity---->DecorView ----->ViewGroup---->View

归是指:事件的消费从 View---->ViewGroup---->DecorView---->Activity

要素,连接关系,运行环境如下图

 

分析 :

1: 方法要素:dispatchTouchEvent是在View中定义的,ViewGroup重写了它。并且View 中的dispatchTouchEvent函数是交给

OnTouchListener处理的,并调用onTouchEvent ----->这是都是View类型控件自己处理

ViewGroup类控件,先是判断是否拦截或者是否禁止拦截这两个变量,来决定是否交给子控件处理,然后才自己处理,自己处理的逻辑和View处理的 逻辑是一样的

2:  要素说明 :

onInterceptTouchEvent(MotionEvent ev) ----》如果返回true,那么子类就没有机会获的事件

onTouchListener.onTouch ----->监听touch事件,onTouch返回值决定是否消费此事件,是否回调onTouchEvent

onTouchEvent ------>控件解析处理事件

setOnClickListener ----->View中的函数,设置点击事件回调onClick函数

3: 关键函数,参数解析

disallowIntercept /  requestDisallowIntercept 变量,是否请求父控件禁止拦截事件,默认是false ---->即 默认是拦截的

 interceptTouchEvent() -----> 1: 一般在滑动冲突的时候,我们复写这个函数,然后在函数里面加上一个判断条件,什么条件下返回true 拦截事件,什么情况下返回false 不拦截事件。2:系统对于这个函数的处理事:判断 用户的触摸事件是在父控件下的子控件范围内,如果在就返回false 否则返回true ,那要是不在子控件范围内(用户就是点击 activity空白处)或者子控件没有消费事件(dispatchTouchEvent() 返回false )那么interceptTouchEvent()还是返回false, 继续执行super.dispatchTouchEvent 但是这个已经是ViewGroup自己的事件执行了

4: View对 dispatchTouchEvent函数的调用 处理关系如果返回true (不管是子类返回还是回调父控件返回),事件都是在这一层结束

1: 判断控件enable是否可用 && 是否设置onTouchListener监听 调用onTouch函数

2: onTouch函数:如果返回 false ,说明没有被消费,继续调用 onTouchEvent, 返回true 直接给dispatchTouchEvent返回true

事件在View这一层消费

     5:View对onTouchEvent函数分析

      该方法会处理一系列的 action_down  action_move  action_up 事件(按下,滑动,抬起),并在 up事件的时候会回调 performClick() 函数,并且回调OnClickListener.onClick()方法

伪代码分析:

       1: ViewGroup 的 dispatchTouchEvent函数 

public boolean dispatchTouchEvent(MotionEvent ev) {final int action = ev.getAction();final float xf = ev.getX();final float yf = ev.getY();final float scrolledXFloat = xf + mScrollX;final float scrolledYFloat = yf + mScrollY;final Rect frame = mTempRect;boolean disallowIntercept = (mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0;if (action == MotionEvent.ACTION_DOWN) {if (mMotionTarget != null) {mMotionTarget = null;}if (disallowIntercept || !onInterceptTouchEvent(ev)) {ev.setAction(MotionEvent.ACTION_DOWN);final int scrolledXInt = (int) scrolledXFloat;final int scrolledYInt = (int) scrolledYFloat;final View[] children = mChildren;final int count = mChildrenCount;for (int i = count - 1; i >= 0; i--) {final View child = children[i];if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE|| child.getAnimation() != null) {child.getHitRect(frame);if (frame.contains(scrolledXInt, scrolledYInt)) {final float xc = scrolledXFloat - child.mLeft;final float yc = scrolledYFloat - child.mTop;ev.setLocation(xc, yc);child.mPrivateFlags &= ~CANCEL_NEXT_UP_EVENT;if (child.dispatchTouchEvent(ev))  {mMotionTarget = child;return true;}}}}}}boolean isUpOrCancel = (action == MotionEvent.ACTION_UP) ||(action == MotionEvent.ACTION_CANCEL);if (isUpOrCancel) {mGroupFlags &= ~FLAG_DISALLOW_INTERCEPT;}final View target = mMotionTarget;if (target == null) {ev.setLocation(xf, yf);if ((mPrivateFlags & CANCEL_NEXT_UP_EVENT) != 0) {ev.setAction(MotionEvent.ACTION_CANCEL);mPrivateFlags &= ~CANCEL_NEXT_UP_EVENT;}return super.dispatchTouchEvent(ev);}if (!disallowIntercept && onInterceptTouchEvent(ev)) {final float xc = scrolledXFloat - (float) target.mLeft;final float yc = scrolledYFloat - (float) target.mTop;mPrivateFlags &= ~CANCEL_NEXT_UP_EVENT;ev.setAction(MotionEvent.ACTION_CANCEL);ev.setLocation(xc, yc);if (!target.dispatchTouchEvent(ev)) {}mMotionTarget = null;return true;}if (isUpOrCancel) {mMotionTarget = null;}final float xc = scrolledXFloat - (float) target.mLeft;final float yc = scrolledYFloat - (float) target.mTop;ev.setLocation(xc, yc);if ((target.mPrivateFlags & CANCEL_NEXT_UP_EVENT) != 0) {ev.setAction(MotionEvent.ACTION_CANCEL);target.mPrivateFlags &= ~CANCEL_NEXT_UP_EVENT;mMotionTarget = null;}return target.dispatchTouchEvent(ev);}

2: View的 dispatchTouchEvent函数 

总结  

   1: android触摸事件是先从 ViewGroup 在传递给View

   2:  ViewGroup 的dispatchTouchEvent 函数 会 根据 disallowIntercept 来决定是否分发给子控件,此变量的作用就是在 interceptTouchEvent 返回true 之后(不允许事件向子类传递)子类还是想收到 事件这个问题。

   3: 子类如果消费事件了,就会通过 dispatchTouchEvent函数传递消费事件的返回值true

  4:  View 的dispatchTouchEvent  会判断 控件是否设置 enable  && onTouchListener 来决定是否走onTouch函数,onTouch函数的返回false, 又会走 onTouchEvent 函数。最终将事件的消费情况传递给 父类

应用:

   说了这么都,实际的应用了 ?

  1: 一般如果自定义控件继承ViewGroup ,那么需要重写 onInterceptTouchEvent() 函数,并根据自己的的业务逻辑灵活的返回true 或者false  -------》比如在ViewPager 中嵌套 ListView 或者RecyclerView 就要控制好 ViewPager 的 onInterceptTouchEvent()函数是否拦截事件了 ,一般都是定义一个 规则,超过某段距离认为用户想横向滑动,这个时候就拦截事件不向RecyclerView 分发,没超过一定距离就 认为用户想垂直滑动,这个时候事件件不拦截事件需要向RecyclerView 分发

 

View系列:事件分发:滑动触摸事件分发相关推荐

  1. 转载大神IOS开发系列【9】--触摸事件、手势识别、摇晃事件、耳机线控

    转载自:http://www.cnblogs.com/kenshincui/p/3950646.html 概览 iPhone的成功很大一部分得益于它多点触摸的强大功能,乔布斯让人们认识到手机其实是可以 ...

  2. iOS事件全面解析 (触摸事件、手势识别、摇晃事件、耳机线控)

    -- iOS事件全面解析 概览 iPhone的成功很大一部分得益于它多点触摸的强大功能,乔布斯让人们认识到手机其实是可以不用按键和手写笔直接操作的,这不愧为一项伟大的设计.今天我们就针对iOS的触摸事 ...

  3. Android View系列(二):事件分发机制源码解析

    概述 在介绍点击事件规则之前,我们需要知道我们分析的是MotionEvent,即点击事件,所谓的事件分发就是对MotionEvent事件的分发过程,即当一个MotionEvent生成以后,系统需要把这 ...

  4. Android 6种触摸事件,Android 的触摸事件详解及示例代码

    由于触摸(Touch)而触发的事件 Android的事件:onClick, onScroll,onFling等等,都是由许多个Touch组成的.其中Touch的第一个状态肯定是ACTION_DOWN, ...

  5. html 禁止触摸事件,html5的触摸事件

    1.触摸事件有哪些 touchstart,touchmove,touchend 2.分别什么时候触发 touchstart事件:当手指触摸屏幕时候触发,即使已经有一个手指放在屏幕上也会触发. touc ...

  6. OpenCV鼠标事件和滑动条事件

    鼠标事件 ① 鼠标事件是通过传统的回调函数机制来完成. void your_mouse_callback(int event, int x, int y, int flags, void* param ...

  7. 事件分发(二)ViewGroup和View对触摸事件的分发流程

    接着上篇<Activity对触摸事件的分发流程>,这篇我们讲<ViewGroup和View对触摸事件的分发流程>. 1.ViewGroup对触摸事件的分发流程 ViewGrou ...

  8. View的事件体系之三 android事件分发机制详解(下)

    接着上一篇来分析事件分发机制,在看了各位大牛的关于事件分发机制的分析后茅塞顿开,之前看过好几遍郭霖,弘扬以及玉刚大神关于事件体系的讲解,一直看不懂,比较模糊,最近复习时,看到一篇博文,写的相当精彩,看 ...

  9. Android触摸事件分发

    Android的触摸分发机制和如何实现拦截 Android的触摸分发机制和如何实现拦截 前言 触摸事件的分发 情景分析 总结 前言 在自定义ViewGroup中,有时候需要实现触摸事件拦截,比如Lis ...

  10. iOS开发系列--触摸事件、手势识别、摇晃事件、耳机线控

    -- iOS事件全面解析 概览 iPhone的成功很大一部分得益于它多点触摸的强大功能,乔布斯让人们认识到手机其实是可以不用按键和手写笔直接操作的,这不愧为一项伟大的设计.今天我们就针对iOS的触摸事 ...

最新文章

  1. Eclipse中Spring插件:Spring Tool 4(aka Spring Tool Suite 4)插件安装
  2. hadoop2.8配置_Hadoop2.8.2安装与配置(单机)
  3. 【Liunx】Linux 简介
  4. 直播丨Oracle 12cR2 ADG LGWR Library Cache案例分享
  5. 卷片机行业调研报告 - 市场现状分析与发展前景预测
  6. Mybatis--关于插入数据后返回id的操作
  7. 如何让Win10在开机时跳过锁屏
  8. python语法笔记-linux
  9. 增加对ARM64和X86的硬件预取控制驱动的支持
  10. 万元怎样保留小数点_如何让数字以万元为单位显示并保留2位小数,且有千位分隔符...
  11. 奋斗吧,程序员——第五十四章 坐拥美人君莫笑,古来征战几人回
  12. 提升研发质量的三个办法
  13. 单片机双字节数乘法运算实验_单片机究竟是如何构成的呢
  14. 软件工程导论项目之小学生四则运算出题软件
  15. 你处在人生的哪个阶段
  16. H5游戏作弊与防作弊——我如何拿到第一名的天猫精灵
  17. 彻底搞懂 RxJava
  18. 数据分析-数据类型及数据收集和整理方法-04
  19. 如何面试软件测试工程师?面试官容易搞定吗?
  20. 直播回顾 | IOT、AI、云计算等融合技术推进制造业产业转型(二)

热门文章

  1. 房产中介管理系统的开发(附源码)
  2. 芯烨网口小票打印机,使用PHP打印小票
  3. 利用sublime3 + xmapp使用服务器调试
  4. 【参赛日记】参加天池大数据竞赛
  5. 关于“Windows无法验证设备所需的驱动程序的数字签名”错误的解决方法
  6. 碧桂园+电子签章系统,打造印控中台,实现集团印章管控一体化
  7. 中国500强企业是如何构建电子签章系统的?
  8. 如何实现电子签章效果
  9. 数据库-英语单词基础笔记-1
  10. 海康、大华、科达、华为摄像机的二次开发Demo、SDK