关于事件分发的文章确实很多,本文仅是用于自己对该知识点的总结和查漏,针对一些疑惑自问自答
描述
谈及事件分发,难免涉及到三个类,三个方法:
事件传递: Activity -> ViewGroup -> View (可理解为三层)
涉及的方法:dispatchTouchEvent, onInterceptTouchEvent(仅ViewGroup中存在), onTouchEvent
其中,dispatchTouchEvent在本层次中最先收到事件,可以在辞呈
为了加深印象,写了一个demo,如下图:

在三个相关的类中,分别重写涉及事件的三个方法,打上日志,点击View,日志如下:
1 | 2019-10-22 23:18:31.732 31871-31871/com.wjp.eventtransferdemo D/MainActivity: dispatchTouchEvent:down |
可以看到,action_down
事件是从dispatchTouchEvent开始,从上到下传递(以树的结构,父View为上,子View为下),经过onInterceptTouchEvent过滤,这里我们不拦截down事件,
事件则能从上流到底端,后onTouchEvent则从下到上传递,可供各级View消费该事件,而之后的action_up
事件为什么仅会从在Activity中传递呢?
这里引出一个最重要的结论:(个人觉得哈)
down事件是所有事件的起点,之后才会有其他事件传递过来,
方法onTouchEvent,决定了要不要消费之后分发过来的事件,如action_up, 在此次例子,默认的View和ViewGroup都返回false,所有他们表示都不要
消费事件,这样,使得之后的事件由最上层View来消费,(Activity中本身其实也可以理解为View,其中包含有Window,Window由包含有DecorView,即
DecorView是所有View的顶层View)。
为了验证此结论,将ViewGroup的onTouchEvent返回true,表示该ViewGroup要消费后续的事件,则之后的up事件只会传到ViewGroup消费,(同理View)
1 | 2019-10-22 23:48:03.346 31871-31871/com.wjp.eventtransferdemo D/MainActivity: dispatchTouchEvent:down |
也可在上面ViewGroup滑动,可以看到,所有的事件(move,up)都传给ViewGroup来消费:
1 | 019-10-22 23:52:08.835 31871-31871/com.wjp.eventtransferdemo D/MainActivity: dispatchTouchEvent:down |
由此,可以得出一个通俗的结论,事件是从上到下询问,确定之后该由谁来处理后续的事件(接受处理任务),直至有人消费则停止询问,若无人去人给最上层处理。
由上面的结论,可得知,若是我(某个不知名的View)想消费事件,只要在down事件来临时,return true, 表示我可以接受任务,那么若是上层和下层都想要
消费事件,该由谁来消费呢?
默认情况下,下层的onTouchEvent先调用,所以当然优先由下层View来处理后续事件;那么若是上层View想要优先与下层来处理事件呢?
比如在ScrollView中,上下滑动时,开始先由子View来出来滑动事件,达到一定条件后拦截后续move事件让ScrollView来处理,源码如下:
1 | //ScrollView |
写一个demo,一个WantToHandlerMoveEventView
尽量的想要消费滑动事件,但是放在ScrollView
里面,上下滑动该自定义View,日志如下:
1 | 2019-10-24 00:31:57.948 27211-27211/com.wjp.eventtransferdemo D/ScrollViewInnerAct: dispatchTouchEvent:down |
由此,我们又可以得到一个结论,若是上下层View都想消费同一个事件,上层View可通过onInterceptTouchEvent获得有权。
这样,通过上面,基本了解三个相关方法的关系。
###相关demo