Android 事件分发:
一、事件分发:
事件:当触摸View ViewGroup派生的控件后,将会触发一系列的触发响应事件
分发:是指一个触摸或点击的事件发生,分发给当前触摸控件监听的事件,进而决定是控件的那个函数来响应此次事件
二、事件作用的对象:
Android的两大基础控件类型: View ViewGroup:
View :一般类型的控件 TextView Button Edittext等;
ViewGroup :组合式控件,LinearLayout RelationLayout 等;
ViewGroup : 继承View;
三、事件的分类:
事件通常重要的有如下三种:
MotionEvent.ACTION_DOWN 按下View 是所有事件的开始
MotionEvent.ACTION_MOVE 滑动事件
MotionEvent.ACTION_UP 与DOWN对应 表示抬起
四、 Touch事件:
Activity的Touch事件事实上是调用它内部的ViewGroup的Touch事件,可以直接当成ViewGroup处理;
Activity 对应的事件只有:dispatchTouchEvent、onTouchEvent;
ViewGroup的相关事件有三个:dispatchTouchEvent、onInterceptTouchEvent、onTouchEvent;
View的相关事件只有两个:dispatchTouchEvent、onTouchEvent;
五、方法的流程:
Touch 事件发生时 Activity 的 dispatchTouchEvent(MotionEvent ev) 方法会以隧道方式(从根元素依次往下传递直到最内层子元素或在中间某一元素中由于某一条件停止传递)将事件传递给最外层 View 的 dispatchTouchEvent(MotionEvent ev) 方法,并由该 View 的 dispatchTouchEvent(MotionEvent ev) 方法对事件进行分发。
1. dispatchTouchEvent 的事件分发逻辑如下:
如果 return true,事件会分发给当前 View 并由 dispatchTouchEvent 方法进行消费,同时事件会停止向下传递;
如果 return false,事件分发分为两种情况:
如果当前 View 获取的事件直接来自 Activity,则会将事件返回给 Activity 的 onTouchEvent 进行消费;
如果当前 View 获取的事件来自外层父控件,则会将事件返回给父 View 的 onTouchEvent 进行消费。
如果返回系统默认的 super.dispatchTouchEvent(ev),事件会自动的分发给当前 View 的 onInterceptTouchEvent 方法
2. onInterceptTouchEvent 的事件拦截逻辑如下:
在外层 ViewGroup 的 dispatchTouchEvent(MotionEvent ev) 方法返回系统默认的 super.dispatchTouchEvent(ev) 情况下,事件会自动的分发给当前 ViewGroup 的 onInterceptTouchEvent 方法。
如果 onInterceptTouchEvent 返回 true,则表示将事件进行拦截,并将拦截到的事件交由当前 View 的 onTouchEvent 进行处理;
如果 onInterceptTouchEvent 返回 false,则表示将事件放行,当前 View 上的事件会被传递到子 View 上,再由子 View 的 dispatchTouchEvent 来开始这个事件的分发;
如果 onInterceptTouchEvent 返回 super.onInterceptTouchEvent(ev),事件默认不会被拦截,并将事件向下传递。
3.onTouchEvent 的事件响应逻辑如下:
在 dispatchTouchEvent 返回 super.dispatchTouchEvent(ev) 并且 onInterceptTouchEvent 返回 true 情况下 onTouchEvent 会被调用。
如果事件传递到当前 View 的 onTouchEvent 方法,而该方法返回了 false,那么这个事件会从当前 View 向上传递,并且都是由上层 View 的 onTouchEvent 来接收,如果传递到上面的 onTouchEvent 也返回 false,这个事件就会“消失”,而且接收不到下一次事件。
如果返回了 true 则会接收并消费该事件。
如果返回 super.onTouchEvent(ev) 默认处理事件的逻辑和返回 false 时相同。
六、事例Dome运行结果分析:
1.默认条件:
分析: onInterceptTouchEvent 返回默认值是 false onTouchEvent 返回默认值是true
遵循了隧道传递方式,由最内层依次传递到最外层,如果没有字View没有处理返回父类处理;
2.1 Activity dispatchTouchEvent 返回false
分析: 没有父类,事件就没有在向上传递处理
2. 如果将dispatchTouchEvent 返回值设置为 true
分析:结束事件的分发, 并且有自己的dispatchTouchEvent方法处理;
3.1 activity dispatchTouchEvent 默认:
ViewGroup dispatchTouchEvent false
分析: ViewGroup 将分发事件返回false 不在向子类进行事件的分发,ViewGroup的触摸事件来自Activity,那么就会将Touch事件上传给Activity的 onTouchEvent 方法处理(即使将ViewGroup 的onInterceptTouchEvent事件的返回值设置为true 同样是不会处理的)
3.2 如果将ViewGroup dispatchTouchEvent 放回值设置为true:
分析:此时Touch事件就有自己的 dispatchTouchEvent 方法消费, 其它方法都不在执行,
(即使将ViewGroup 的 onInterceptTouchEvent onTouchEvent 返回值改变结果都保持不变)
4.1 activity 默认条件
ViewGroup dispatchTouchEvent 返回 默认
onInterceptTouchEvent 返回 true(默认)
分析: 当ViewGroup的onInterceptTouchEvent 返回值设置为 true 时,那么就会拦截Touch事件,即使分发是默认的向下分发,此时也不会再向下分发事件,由于ViewGroup的onTouchEvent 事件默认是false 不处理,因此将Touch事件返回给Activity进行处理;
4.2 如果 将 ViewGroup的onTouchEvent 返回值设置为true:
此时ViewGroup 不仅拦截了事件,而且处理了事件
5.1 activity 默认条件
ViewGroup 所有方法都返回默认状态
View的 dispatchTouchEvent 返回值设置false
分析: 由于View的dispatchTouchEvent返回的是 false ,因此会将Touch事件上传给父类处理,由于ViewGroup的onTouchEvent放回的是false ,ViewGroup就不会再处理该事件,在上传给Activity进行处理
5.2 如果将ViewGroup onTouchEvent方法设置为true结果如下:
如果ViewGroup的onTouchEvent方法的返回值设置true 那么ViewGroup就会处理掉该事件;
6.1 activity 默认条件
ViewGroup 所有方法都返回默认状态
View的 dispatchTouchEvent 返回值设置true
分析:View 的 dispatchTouchEvent 放回true 那么Touch事件将由自己的dispatchTouchEvent消费
6.2 如果将View 的dispatchTouchEvent 设置为默认状态,并将View的onTouchEvent 事件返回值设置为false 结果为下:
事件由View的父类处理