您的位置:首页 > 移动开发 > Android开发

android触摸事件流程(一)

2015-06-19 15:50 309 查看
对于android的触摸事件,一直以来都有点模糊,所以决定搞搞清楚.这里一共分三部分来解决这个问题:第一部分:触摸事件是如何起源的.第二部分:view是如何处理触摸事件的.第三部分:viewgroup是如何分发和处理触摸事件的.

这一次先看第一部分:触摸事件是如何起源的.

要理解这个问题,首先应该知道下面三点:

每一个需要显示到手机上的视图最总都是通过WindowManager.addview()的方式来实现的,比如我们常用的activity/popwindow/状态栏/锁屏/来闹钟界面等!
在WindowManager.addview()过程中实际上是调用WindowManagerGlobal.addView(),在这个方法里面是通过创建一个ViewRootImpl的对象,最后将需要显示的视图view加入到这个ViewRootImpl.也就是说显示的视图起源于ViewRootImpl.
一个activity的视图起源于一个DecorView:DecorView其实是一个FrameLayout,我们在activity中通过setContentView()添加的显示view最终都是会加入这个DecorView里面的.

下面来看看触摸事件流程,看看触摸事件是如何流入视图的view的:

(1)每一个显示的窗口都是需要通过WindowManager.addview()来添加进去的,这个过程中会为这个显示的view创建一个该view与系统交互的ViewRootImpl.这里的触摸事件就是开始从ViewRootImpl来的.

(2)ViewRootImpl中定义了一个WindowInputEventReceiver来接收触摸事件.然后把触摸事件传递给mView.在activity中mView就是DecorView

(3)通过ViewRootImpl最后调用了view的dispatchPointerEvent(MotionEvent event).这样触摸事件就传递给了显示的view了

我们知道,对于activity来说,ViewRootImpl首先时把触摸事件传递给了DecorView的dispatchPointerEvent().下面来看看DecorView的dispatchPointerEvent源码:

public boolean dispatchTouchEvent(MotionEvent ev) {

final Callback cb = getCallback();

return cb != null && !isDestroyed() && mFeatureId < 0 ? cb.dispatchTouchEvent(ev)//会首先调用Callback的dispatchTouchEvent方法.

: super.dispatchTouchEvent(ev);

}

这里要知道这个Callback对象那里来的.来看看getCallback()的源码,在Window里面定义如下:

public final Callback getCallback() {

return mCallback;//看到了吧,其实很简单,直接返回mCallback即可.

}

那么mCallback是在何时赋值的呢?我们知道,创建一个activity就会为这个activity创建他的window,在activity中你会发现:原来activity已经implements了这个Callback

通过activity的代码你会发现其实在创建window的时候就给这个window的mCallback赋值了:

mWindow = PolicyManager.makeNewWindow(this);

mWindow.setCallback(this);//这里的this就是当前的activity

所以最终DecorView调用 dispatchTouchEvent会调用到activity的dispatchTouchEvent()方法.

(4)来看看activity的dispatchTouchEvent做来些什么:

public boolean dispatchTouchEvent(MotionEvent ev) {

if (ev.getAction() == MotionEvent.ACTION_DOWN) {

onUserInteraction();

}

if (getWindow().superDispatchTouchEvent(ev)) {//会调用Window的superDispatchTouchEvent方法,如果返回true,则结束,否则调用这个activity的onTouchEvent方法

return true;

}

return onTouchEvent(ev);

}

(5)所以来看看 Window的superDispatchTouchEvent方法.Window是一个虚类,其实现类是PhoneWindow

public boolean superDispatchTouchEvent(MotionEvent event) {

return mDecor.superDispatchTouchEvent(event);//实际上是调用DecorView的superDispatchTouchEvent方法

}

(6)来看看DecorView的superDispatchTouchEvent的

public boolean superDispatchTouchEvent(MotionEvent event) {

return super.dispatchTouchEvent(event);//看到了吧,最终还是调用了DecorView的dispatchTouchEvent方法

}

(7)综上所述:触摸事件从 ViewRootImpl开传递出来,最终会调用显示视图view的最父(最后面的/最老的)view的dispatchTouchEvent.如果返回false,就会调用activity的onTouchEvent()方法.

从上面的分析可以看出,触摸事件都是从dispatchTouchEvent开始的,所以要理解触摸事件的流程其实就要从view的dispatchTouchEvent开始.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: