android觸摸事件流程(一)

來源:互聯網
上載者:User

標籤:android開發   frameworks   源碼   

      對於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開始.

android觸摸事件流程(一)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.