Android事件分发总结
Posted 不会写代码的丝丽
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android事件分发总结相关的知识,希望对你有一定的参考价值。
总是忘记又要去看源码所以直接记下结果方便以后阅读:
假设当前是
假设View的ClickAble为false(如果为true默认消费事件)decorView我们接触不到但是我还是想写下来
事件传播(默认):
触摸事件按下
1 Activity->dispatchTouchEvent
2 decorView->dispatchTouchEvent
不做详细分析因为我们开发者控制不到
3 decorView->onInterceptTouchEvent
4 开发者的ViewGroup->dispatchTouchEvent
5 开发者的ViewGroup->onInterceptTouchEvent
6 View->dispatchTouchEvent
7 View->onTouchEvent
8 ViewGroup->onTouchEvent
9 decorView->onTouchEvent
10 activity->onTouchEvent
触摸事件移动(因为上面的没有消费所以直接在Activity中消费)
11 Activity->dispatchTouchEvent
12 decorView->dispatchTouchEvent
(不会触发
onInterceptTouchEvent
因为内部mFirstTouchTarget
为空)
13 activity->onTouchEvent
触摸事件抬起(因为上面的没有消费所以直接在Activity中消费)
14 Activity->dispatchTouchEvent
15 decorView->dispatchTouchEvent
(不会触发
onInterceptTouchEvent
因为内部mFirstTouchTarget
为空)
16 activity->onTouchEvent
备注:
1 如果任意ViewGroup
中如果onInterceptTouchEvent
返回了一次true
那么在本触摸事件的后序事件不会在调用onInterceptTouchEvent
进行判断。假设触摸事件为
①按下 ②移动 ③移动 ④松开
假设在①按下事件调onInterceptTouchEvent
返回了false
②移动事件调用 onInterceptTouchEvent
返回了true
那么 ③移动 和 ④松开不会调用到onInterceptTouchEvent
。 注意啊不影响dispatchTouchEvent
收到完整通知,除非在触摸按下事件的时候dispatchTouchEvent
返回了false
。
1.1 如果任意ViewGroup
中如果onInterceptTouchEvent
返回了true那么直接会调用super.onInterceptTouchEvent
从而直接调用本ViewGroup
的ontouchEvent
.
2 View
的dispatchTouchEvent
的实现默认调用onTouchEvent
并作为返回值
3.1 ViewGroup
的dispatchTouchEvent
会调用onInterceptTouchEvent
如果返回true
那么会调用自身父类的View
的dispatchTouchEvent
也就是直接调用自身的onTouchEvent
。如果onInterceptTouchEvent
返回false
交给子布局类的dispatchTouchEvent
决定其自身的dispatchTouchEvent
返回值。如果子布局类的dispatchTouchEvent
返回false
,那么调用ViewGroup
的父类(也就是ViewGroup的父类View,简单点就是super.dispatchTouchEvent)的dispatchTouchEvent
决定返回值。
3.2 如果ViewGroup
在触摸按下的时候dispatchTouchEvent
返回false
那么dispatchTouchEvent
收不到后序事件。
①按下 ②移动 ③移动 ④松开
假设上面的四个事件①返回了false ,②③④将收不到通知。
3.3 如果ViewGroup
在触摸按下dispatchTouchEvent
的时候返回true
,会收到后序事件,哪怕你在移动事件返回了false
依然会继续收到后序事件,只要你在按下事件返回了true
①按下 ②移动 ③移动 ④松开
假设上面的四个事件①返回了true ,②返回了false,③和 ④你依然会接受到事件通知。
3.4 onTouchEvent
方法内部会判断手指松开事件然后回调onClick。并且该方法默认返回值的在该View为Clickable时返回true。也就是不调用默认实现无法监听点击事件
3.4 不管是ViewGroup
还是View
设置了OnTouch
监听那么调用onTouchEvent
前会调用OnTouch
方法,如果OnTouch
方法返回了true那么不会在调用onTouchEvent
,返回false那么才会调用onTouchEvent
4 中途拦截返回true情况。假设有如下情况
①按下 ②移动 ④松开
View
在DispatchTouchEvent
直接返回了super.dispatchTouchEvent(ev) || true
ViewGroup
的onInterceptTouchEvent
方法如果是移动事件那么返回true
,其它触摸事件false
那么事件序列为
触摸事件按下
1 Activity->dispatchTouchEvent
2 decorView->dispatchTouchEvent
3 decorView->onInterceptTouchEvent
4 开发者的ViewGroup->dispatchTouchEvent
5 开发者的ViewGroup->onInterceptTouchEvent
返回false
6 View->dispatchTouchEvent
返回true
7 View->onTouchEvent
触摸事件移动
8 Activity->dispatchTouchEvent
9 decorView->dispatchTouchEvent
10 decorView->onInterceptTouchEvent
11 viewGroup->onInterceptTouchEvent
此时返回了true ,因为返回了true下次后续事件不会调用,注意dispatchTouchEvent不影响后序事件接收
12 View->dispatchTouchEvent
会受到一个cancel的触摸事件注意不是移动事件
13 View->onTouchEvent
会受到一个cancel的触摸事件注意不是移动事件。如果有监听点击事件此处也不会当抬起事件处理,也就是你设置了监听点击事件的将不会受到回调
触摸事件抬起(因为上面的没有消费所以直接在Activity中消费)
14 Activity->dispatchTouchEvent
15 decorView->dispatchTouchEvent
16 decorView->onInterceptTouchEvent
17 viewGroup->dispatchTouchEvent
不会调用拦截方法了哦。拦截方法返回了true后序事件不会在拦截判断了
18 viewGroup->onTouchEvent
看清楚了哦
5 ViewGroup 的 在受到按下事件的时候dispatchTouchEvent 返回false 后序事件将接收不到。假设按下返回true 移动的事件返回false 依然能接收到后序事件
6 ViewGroup
的 在受到按下事件的时候dispatchTouchEvent
返回true
且不调用super.dispatchTouchEvent
那么onInterceptTouchEvent
和onTouchEvent
不会调用。
7 ViewGroup
的 在受到按下事件的时候dispatchTouchEvent
返回true||super.dispatchTouchEvent
并且onInterceptTouchEvent
返回了true
,那么直接调用onTouchEvent
且后序事件不会在调用经过onInterceptTouchEvent
而是直接dispatchTouchEvent
到onTouchEvent
8 Activity
的onTouchEvent
只有在子View
的按下事件dispatchTouchEvent
返回false
时才会调用,也就是后序事件(注意是按下之后的关联后序事件)子ViewdispatchTouchEvent
哪怕返回false (按下事件就是一个新的触摸事件),activity的 onTouchEvent
也不会回调
用法解析
当一个ViewGroup不想子View调用触摸事件时onInterceptTouchEvent 返回true。如果自己想消费那么onInterceptTouchEvent返回true且dispatchTouchEvent返回true,根据自身情况判断是否要super.dispatchTouchEvent
View
是否会默认消费事件
如果View 的clickable或者longClickAble为true 那么不管是否enable都会消费事件
源码原理解析总结:
ViewGroup
继承View
,ViewGroup
重写了View
的dispatchTouchEvent
方法。内部调用逻辑大致如下
1 是否是按下事件?如果是调用onInterceptTouchEvent
方法,如果onInterceptTouchEvent
返回true
那么调用View的dispatchTouchEvent
方法且返回值作为自身返回值,而View
默认dispatchTouchEvent
实现为直接调用onTouchEvent
作为返回值。onTouchEvent
内部实现了点击监听的回调。
2 是否是按下事件?如果是调用onInterceptTouchEvent
方法,如果onInterceptTouchEvent
返回false
遍历子View
的dispatchTouchEvent
方法,如果子View
的dispatchTouchEvent
返回true,ViewGroup
中一个属性mFirstTouchTarget
保存这个View
3 不是按下事件且mFirstTouchTarget
为空那么 直接调用ViewGroup
的super.dispatchTouchEvent
从而调用自身onTouchEvent
3 不是按下事件且mFirstTouchTarget
不为空那么, 直接调用ViewGroup
的onInterceptTouchEvent
,如果返回为true
,那么调用mFirstTouchTarget
的dispatchTouchEvent
方法并且触摸事件变为取消事件cancel
且mFirstTouchTarget
重变为null;另一种情况ViewGroup
的onInterceptTouchEvent
返回false,那么调用mFirstTouchTarget
的dispatchTouchEvent
方法,注意这里不会重置mFirstTouchTarget
属性
以上是关于Android事件分发总结的主要内容,如果未能解决你的问题,请参考以下文章