從ListView與ScrollView的衝突調查android view的事件處理機制

當我們做項目時經常會遇到整體界面需要滑動,此頁面中又有ListView的 情況。比如說:某法院系統的提交訴訟材料界面,這種界面要提交很多元素,其中想證人可能有多個,就會用到ListView。但這種ScrollView裏 包含ListView的情況下,ListView是無法滾動的。很多人都知道這個現象,但爲什麼會出現這個問題呢?這就要追溯到我們今天要講的 android View的事件處理機制。

首先我們先看這個問題爲什麼會產生呢?我們調查ScrollView的代碼會發現,如下

public boolean onInterceptTouchEvent(MotionEvent ev) {

    final int action = ev.getAction();
    if ((action == MotionEvent.ACTION_MOVE) && (mIsBeingDragged)) {
        return true;
    }
}

這個方法是touch事件的攔截方法,當用戶拖動屏幕,就會被這個方法攔截下來,返回true,所以ListView的滾動就失效了。這裏又扯出onInterceptTouchEvent方法,這個方法又是什麼呢?

View整個體系提供了3個對事件操作:

  1. dispatchTouchEvent。事件分發,主要是體系的上層向下層,層級形式分發事件的機制。
  2. onInterceptTouchEvent。事件攔截,主要是攔截事件,並阻止其進一步傳遞到體系下層的機制。
  3. onTouchEvent。事件處理,主要是事件接收並做出處理,並向體系上層傳遞處理結果的機制。

通過這三種操作,對View體系中的事件作出管理。那我們現在已經知道了問題出現的原因:是因爲用戶的拖動事件被ScrollView的onInterceptTouchEvent方法攔截住了,那事件又是怎麼傳遞過來的呢?

當手機屏幕被用戶觸摸,就會形成一套事件序列,每一套事件序列都有三種事件動作(down,move,up)組合完成。 這套序列會被傳遞到系統framework層,再傳入Activity,然後Activity會把事件傳給Window下的DecorView進行分發, 分發給每個View。而某個View的onTouchEvent處理了這個事件,並返回true,就說明此事件已傳遞完畢。

說到返回值,這三個方法的返回值含義如下:

  • dispatchTouchEvent
    true:事件被以該節點爲根節點的View樹成功處理,此時該事件就算是處理完成了,事件不會再向上返還給View的父節點。
    false:以該節點爲根節點的View樹中,沒有一個View成功處理了此事件,所以事件會向上返還給View的父節點。
  • onInterceptTouchEvent
    true:當前ViewGroup希望該事件不再傳遞給其下層,而是希望自己處理。
    false:當前ViewGroup不準備攔截該事件,事件將正常向下分發給其下層。

  • onTouchEvent
    true:表示該View成功處理了該事件,該處理結果會向上通知給其上層。
    false:表示該View沒有成功處理該事件。

到此,瞭解了這麼多再回顧一下開始的問題,原因是事件被ScrollView攔截到了,那解決方法有很多,最直接的一種就是當我們滑動ListView時不讓ScrollView攔截到。那要怎麼做呢?

通知其上層不要攔截此事件。代碼如下:

public boolean onTouchEvent(MotionEvent ev) {  
    super.onTouchEvent(ev);  
    switch (ev.getAction()) {  
        case MotionEvent.ACTION_DOWN:  
            getParent().requestDisallowInterceptTouchEvent(true);  
            break;  
        case MotionEvent.ACTION_MOVE:  
            break;  
        case MotionEvent.ACTION_UP:  
            getParent().requestDisallowInterceptTouchEvent(false);  
            break;  
        default:  
            break;  
    }  
    return  true;  
}

以上就是從ListView與ScrollView的衝突調查android view的事件處理機制,希望對大家有所幫助。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章