View系列:事件分发:滑动触摸事件分发
参考博客:即于下面博客演变出自己的理解
【透镜系列】看穿 > 触摸事件分发 > - 掘金
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系列:事件分发:滑动触摸事件分发相关推荐
- 转载大神IOS开发系列【9】--触摸事件、手势识别、摇晃事件、耳机线控
转载自:http://www.cnblogs.com/kenshincui/p/3950646.html 概览 iPhone的成功很大一部分得益于它多点触摸的强大功能,乔布斯让人们认识到手机其实是可以 ...
- iOS事件全面解析 (触摸事件、手势识别、摇晃事件、耳机线控)
-- iOS事件全面解析 概览 iPhone的成功很大一部分得益于它多点触摸的强大功能,乔布斯让人们认识到手机其实是可以不用按键和手写笔直接操作的,这不愧为一项伟大的设计.今天我们就针对iOS的触摸事 ...
- Android View系列(二):事件分发机制源码解析
概述 在介绍点击事件规则之前,我们需要知道我们分析的是MotionEvent,即点击事件,所谓的事件分发就是对MotionEvent事件的分发过程,即当一个MotionEvent生成以后,系统需要把这 ...
- Android 6种触摸事件,Android 的触摸事件详解及示例代码
由于触摸(Touch)而触发的事件 Android的事件:onClick, onScroll,onFling等等,都是由许多个Touch组成的.其中Touch的第一个状态肯定是ACTION_DOWN, ...
- html 禁止触摸事件,html5的触摸事件
1.触摸事件有哪些 touchstart,touchmove,touchend 2.分别什么时候触发 touchstart事件:当手指触摸屏幕时候触发,即使已经有一个手指放在屏幕上也会触发. touc ...
- OpenCV鼠标事件和滑动条事件
鼠标事件 ① 鼠标事件是通过传统的回调函数机制来完成. void your_mouse_callback(int event, int x, int y, int flags, void* param ...
- 事件分发(二)ViewGroup和View对触摸事件的分发流程
接着上篇<Activity对触摸事件的分发流程>,这篇我们讲<ViewGroup和View对触摸事件的分发流程>. 1.ViewGroup对触摸事件的分发流程 ViewGrou ...
- View的事件体系之三 android事件分发机制详解(下)
接着上一篇来分析事件分发机制,在看了各位大牛的关于事件分发机制的分析后茅塞顿开,之前看过好几遍郭霖,弘扬以及玉刚大神关于事件体系的讲解,一直看不懂,比较模糊,最近复习时,看到一篇博文,写的相当精彩,看 ...
- Android触摸事件分发
Android的触摸分发机制和如何实现拦截 Android的触摸分发机制和如何实现拦截 前言 触摸事件的分发 情景分析 总结 前言 在自定义ViewGroup中,有时候需要实现触摸事件拦截,比如Lis ...
- iOS开发系列--触摸事件、手势识别、摇晃事件、耳机线控
-- iOS事件全面解析 概览 iPhone的成功很大一部分得益于它多点触摸的强大功能,乔布斯让人们认识到手机其实是可以不用按键和手写笔直接操作的,这不愧为一项伟大的设计.今天我们就针对iOS的触摸事 ...
最新文章
- Eclipse中Spring插件:Spring Tool 4(aka Spring Tool Suite 4)插件安装
- hadoop2.8配置_Hadoop2.8.2安装与配置(单机)
- 【Liunx】Linux 简介
- 直播丨Oracle 12cR2 ADG LGWR Library Cache案例分享
- 卷片机行业调研报告 - 市场现状分析与发展前景预测
- Mybatis--关于插入数据后返回id的操作
- 如何让Win10在开机时跳过锁屏
- python语法笔记-linux
- 增加对ARM64和X86的硬件预取控制驱动的支持
- 万元怎样保留小数点_如何让数字以万元为单位显示并保留2位小数,且有千位分隔符...
- 奋斗吧,程序员——第五十四章 坐拥美人君莫笑,古来征战几人回
- 提升研发质量的三个办法
- 单片机双字节数乘法运算实验_单片机究竟是如何构成的呢
- 软件工程导论项目之小学生四则运算出题软件
- 你处在人生的哪个阶段
- H5游戏作弊与防作弊——我如何拿到第一名的天猫精灵
- 彻底搞懂 RxJava
- 数据分析-数据类型及数据收集和整理方法-04
- 如何面试软件测试工程师?面试官容易搞定吗?
- 直播回顾 | IOT、AI、云计算等融合技术推进制造业产业转型(二)