android触摸事件流程(一)

来源:互联网 发布:查看淘宝店铺数据 编辑:程序博客网 时间:2024/06/07 18:40
      对于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开始.
0 0
原创粉丝点击