Pich Blog

关注移动开发,大数据,云计算,软件架构!

10.从源码分析View的事件分发

概述

理解事件分发最好的办法就是看源码。源码版本7.1.1_r6。

Activity对事件的分发

在android中点击事件用MotionEvent来表示,当一个操作发生时,事件会首先传递到当前的Activity,由Activity的dispatchTouchEvent方法来进行分发,具体的工作是由Activity内部的Window来完成的。

Window又将事件传递给decor view,decor View一般就是当前界面的底层容器(即setContentView所设置的View的父容器),而Activity是通过getWIndow.getDecorView()拿到的。

我们先看Activity的dispatchTouchEvent方法:

Activity#dispatchTouchEvent

可以看到如果事件类型等于ACTION_DOWN,他调用了onUserInteraction,但这个方法默认是空实现。然后将事件交给的Activity所附加的Window进行分发,如果返回true,整个事件分发就结束了,返回false就表示没人处理,也就是说所有的View都返回了false,那么Activity的onTouchEvent方法会被调用。

下面我们来看看Window是如何将事件传递给ViewGroup的。我们知道Window是个抽象类,而superDispatchTouchEvent方法也是抽象的,所以我们必须找到他的实现类。实现类就是PhoneWindow。

PhoneWindow#dispatchTouchEvent

可以看到PhoneWindow又将事件传递给了DecorView。

我们在来看看DecorView

DecorView

下看看他的声明,发现他是一个FrameLayout,也就是说到这一步事件已经传递到了View上了。

可以看到的他的dispatchTouchEvent,分两种情况一种是分发给Window.Callback。另一种就是分发到了view上的dispatchTouchEvent方法,这里的super其实调用的是ViewGroup的dispatchTouchEvent方法。

也就说这样我们可以获取根布局:

ViewGroup的事件分发

上面我看看事件已经传到了DecorView,也就是说已经传到了ViewGroup,所以接下来我们看看ViewGroup的事件分发就行了。

总结:

根据1处代码的分析得出结论:当ViewGroup决定拦截事件后,那么后续事件序列将会默认交个他处理,不再调用onInterceptTouchEvent方法,证明了总结3。通过FLAG_DISALLOW_INTERCEPT我们可以干预父类的事件分发,也就是说可以通过这中方法解决ViewGroup和子View的事件冲突。证明了11

View的事件分发

View的事件分发就简单了,因为他没有子View。

上面我们看到他讲事件要么分发到mOnTouchListener,要么分发到自己的onTouchEvent,接下来我们在看看onTouchEvent。

onTouchEvent

该方法可以说是很重要的,因为在这里处理了点击,长按事件。

同时setOnClickLisener方法里面会设置click为true。

事件分发的源码大体就分析完了,下一节讲解如何解决滑动冲突。

点赞

发表评论

电子邮件地址不会被公开。 必填项已用*标注