事件分发传递过程
一 是什么,怎么用,为什么
事件分发传递过程,点击/触摸在Activity和控件之间,控件和控件之间的传递过程,明白点击事件由哪个对象发出,经过哪些对象,最终到达哪个对象并最终得到处理。了解并熟悉有助于分析各种滑动失效问题
为什么要有事件分发传递
Android的view是树形结构的,view可能会重叠在一起,当我们点击/触摸的时候,这个事件该给谁
所以制定一个机制,先保证这个事件能传递到每一个view去,然后哪个view想消费这个事件,就拦截这个事件,消费掉它
二 学习之前应该了解
事件分发的三个方法
- dispatchTouchEvent 事件分发
- onInterceptTouchEvent 阻拦机制
- onTouchEvent 消费机制
- requestDisallowInterceptTouchEvent 子类请求父类解除限制
MotionEvent
-
ACTION_DOWN
-
ACTION_MOVE
-
ACTION_UP
-
ACTION_CANCEL
三 过程
我们可以简化成一个3层的流程图来解释和说明
从上往下依次是Activity、ViewGroup、View
##ACTION_DOWN
- 事件由activity的dispatchTouchEvent做分发
传递方向向下:dispatchTouchEvent和onTouchEvent返回true就不会向下传递了;
传递方向向上:onTouchEvent返回false才会向上传递,返回true不会传了
Android事件分发是先传递到ViewGroup,ViewGroup传递到View。
如果在ViewGroup中通过onInterceptTouchEvent对事件传递进行拦截,返回true,即不允许事件向子View传递,然后调用本身的onTouchEvent事件,进行处理,此时onTouchEvent也具有true和false,True代表事件已经被view所消化;false会往上传递,一直到activity中;
onInterceptTouchEvent返回false代表不拦截事件,即允许事件继续向子view传递,子view如果将传递到事件消费掉,ViewGroup中将无法接收到任何事件
事件的响应顺序
onTouch和onClick事件同时发生
onTouch的执行先于onClick的执行
优先级:OnTouchListener > onTouchEvent > OnClickListener
onTouch以及onTouchEvent的区别
这两个方法都是在View的dispatchTouchEvent中调用的,onTouch优先于onTouchEvent执行,如果在onTouch方法中通过返回true将事件消费掉,onTouchEvent将不会再执行
onTouch能够执行的前提是mOnTouchListener的值不能为空,点击的控件必须是enable的,mOnTouchListener.onTouch返回为true
Button点击的调用过程
Button/dispatchTouchEvent—TextView—View/dispatchTouchEvent
ViewGroup点击调用过程
点击ViewGroup时候,会先去寻找ViewGroup下面的所有子view,直到找到当前点击的区域View,调用child.dipatchTouchEvent
注意
如果执行ACTION_DOWN的时候返回了false,后面ACTION_MOVE,ACTION_UP就不会得到执行了,简单来说就是当dispatchTouchEvent在进行事件分发的时候,只有前一个action返回true,才会触发后一个action?
题目
- 为什么我们在onTouchEvent中返回ture不会执行onclick事件呢
OnClickListener.onClick()是在原生的View.onTouchEvent()方法里面回调的, 你自己重写了这个方法, 而且不调用super.onTouchEvent(event)的话当然就不会回调onClick()方法了 - 如果子控件被限制住了,应该如何进行使他的操作没有被限制?
根据上面源码我们可以,重写onTouchEvent ,使父控件不会限制住
getParent().requestDisallowInterceptTouchEvent(true);
参考学习博客:
https://blog.csdn.net/weixin_39460667/article/details/82991688
https://blog.csdn.net/lijiuche/article/details/70807672//demo研究事件传递
https://www.jianshu.com/p/303d0e6f3f69
https://www.cnblogs.com/aademeng/articles/10702653.html//滑动冲突解决
Activity dispatchTouchEvent事件分发的源头
WMS获取Touch事件
—>ViewRootImpl.deliverInputEvent
—>ViewRootImpl$InputStage(即ViewPostImeInputStage).deliver【这个过程不同Android版本不一样】
—>ViewRootImpl$ViewPostImeInputStage.onProcess
—>ViewRootImpl$ViewPostImeInputStage.processPointerEvent【这一步可以根据InputDevice.SOURCE_CLASS_POINTER这个常量来找】
—>mView.dispatchPointerEvent(event);【这里的mView就是DecorView】
—>Activity.dispatchTouchEvent
【Activity.dispatchTouchEvent是来自Window.Callback.dispatchTouchEvent,Activity.dispatchTouchEvent调用的位置是在PhoneWindow.DecorView. dispatchTouchEvent,此处指的是DecorView它本身重写的那个,而不是super的,注意两者的区别】
接下来就根据艺术探索里的去看吧
以上分析源于API23源码
https://blog.csdn.net/conan9715/article/details/78529055
本文地址:https://blog.csdn.net/weixin_42547039/article/details/108988016
上一篇: 引入并使用axios