Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android進階之事件攔截處理機制

Android進階之事件攔截處理機制

編輯:關於Android編程

1 Android控件架構

這裡寫圖片描述

這裡寫圖片描述

這裡寫圖片描述

1 簡單的總結

(1)父View優先攔截當前事件,攔截不成功就讓子View對當前事件進行攔截。
(2)如果攔截成功的話,就會沿著子view到父View的路徑查找onTouchEvent返回true的那個子View,讓該子View對該事件進行處理;
(3)同時如果某一個View對當前事件攔截成功的話,當前事件就不會繼續分發給這個View的子View。

2 事件分發與處理

2.1 結論

(1)android對事件分發的順序為:Activity–>PhoneWindow->DecorView->yourView;
(2)android控件對事件處理的優先級:onTouch>onTouchEvent>onClick

2.2 事件分發

android既然可以對事件進行攔截,肯定有某個方法對事件進行的傳遞或者分發。完成事件分發功能的方法由Activity的dispatchTouchEvent(MotionEvent ev)l來負責:

    public boolean dispatchTouchEvent(MotionEvent ev) {  
            if (ev.getAction() == MotionEvent.ACTION_DOWN) {  
                //該方法為空方法,直接忽略之    
                onUserInteraction();  
            }  
             //把事件ev交給phoneWindow來處理  
             if (getWindow().superDispatchTouchEvent(ev)) {  
                //表明整個事件到此結束,處理完畢  
                return true;  
            }  
            //說明該事件在View中沒有得到處理,由Activity自己處理  
            //至於怎麼處理博客後面後有說明  
            return onTouchEvent(ev);  
        }  

PhoneWindow方法都做了些什麼:

    @Override  
       public boolean superDispatchTouchEvent(MotionEvent event) {  
           return mDecor.superDispatchTouchEvent(event);  
       }  

就是把此次事件直接很光棍的傳給DecorView,這個View是所有視圖的根視圖,Activity界面中你能見到的各個View都是DecorView的子View。

2.3 事件處理

到此為止事件已經分發到View上面,View獲取到事件後有兩個選擇:處理和不處理該事件,如果處理該事件那事件就不會繼續向其子View分發下去;否則就繼續分發下去交給子View對該事件做同樣的判斷,其實就是個遞歸的過程。

先用如下的偽代碼也表示一下事件處理流程:

    public boolean dispatchTouchEvent(event){  
      //如果當前View對此事件攔截成功  
      if(this.onInterceptTouchEvent(event)){  
          //由當前View對此事件進行處理  
         //true 表示處理了該事件,false表示沒有處理該事件  
            return onTouchEvent(event);  
      }else{//沒有攔截成功  
           //交給子類來分發攔截處理  
            return child.dispatchTouchEvent(event);  
      }  
    }  

更直觀的用流程圖可以如下表示:

這裡寫圖片描述vcC0tKbA7aGjPC9zdHJvbmc+PC9wPg0KPGgzIGlkPQ=="24-分析viewgroup分發事件">2.4 分析ViewGroup分發事件

(1)ViewGroup永遠不會對攔截,因為他的onInterceptTouchEvent(MotionEvent ev)始終返回的是false!這樣DecorView對到來的事件MotionEvent就只有分發到子View並由子View進行攔截和處理此事件了.

(2)View包括直接繼承於View的子類因為其父類View沒有onInterceptTouchEvent方法,所以沒法對事件進行攔截,如果這種View獲取到了事件,那麼就會執行onTouchEvent方法。

3 圖例解析

3.1 情況1

如果A的InterceptTouchEvent返回了true,其余的仍然返回false,那麼執行輸出的log為:
這裡寫圖片描述

轉換成效果圖為:

這裡寫圖片描述

可以發現此時A攔截了此次Touch事件,事件不再向A的子控件B、C、D傳遞。此時所有的action事件比如手指移動ACTION_MOVE或者ACTION_UP等事件都交給A的onTouchEvent方法去處理(當然這是在onTouchEvent方法返回true的情況下,如果返回false經過測試時不會相應這些action的)。B、C、D控件是的事件處理攔截方法和事件處理方法是無法得到執行的。

3.2 情況2

只有B的onIntercepteTouchEvent事件返回了true的情況下,打印的log為
這裡寫圖片描述

轉換成效果圖為:
這裡寫圖片描述

3.3 情況3

同理可知,C控件的onIntercept方法返回了true的情況下,其余的仍然返回false的情況下,輸出log為
這裡寫圖片描述

轉換成效果圖為

這裡寫圖片描述

3.4 下面說說各個view的onTouchEvent返回true的情況

由於onTouchEvent事件是從子控件到父控件傳遞的,當D的onTouchEvent返回true的時候,經測試輸出效果如下

這裡寫圖片描述

轉換成效果圖為:
這裡寫圖片描述

經過測試發現,此時D處理了此次Touch事件的各種action,C B D是的onTouchEvent的沒有得到執行。

同理當C的onTouchEvent方法返回了true的時候,輸出的log如下

這裡寫圖片描述

轉換成效果圖如下:

這裡寫圖片描述

 

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved