onInterceptTouchEvent()與onTouchEvent()的機制

來源:互聯網
上載者:User

http://blog.csdn.net/nexttake/article/details/8243981

測試工程:

TouchTest.zip

http://download.csdn.net/detail/victoryckl/5005142

首先,看Android的官方文檔正解

onInterceptTouchEvent()與onTouchEvent()的機制:

  1. down事件首先會傳遞到onInterceptTouchEvent()方法

  2. 如果該ViewGroup的onInterceptTouchEvent()在接收到down事件處理完成之return false,那麼後續的move, up等事件將繼續會先傳遞給該ViewGroup,之後才和down事件一樣傳遞給最終的目標view的onTouchEvent()處理

  3. 如果該ViewGroup的onInterceptTouchEvent()在接收到down事件處理完成之後return true,那麼後續的move, up等事件將不再傳遞給onInterceptTouchEvent(),而是和down事件一樣傳遞給該ViewGroup的onTouchEvent()處理,注意,目標view將接收不到任何事件。

  4. 如果最終需要處理事件的view的onTouchEvent()返回了false,那麼該事件將被傳遞至其上一層次的view的onTouchEvent()處理

  5. 如果最終需要處理事件的view 的onTouchEvent()返回了true,那麼後續事件將可以繼續傳遞給該view的onTouchEvent()處理。

        這裡的上一層view只的是布局之間的父子關係,和繼承沒有任何關係。

僅僅看這個官方文檔解釋,就能理解清楚這兩個函數關係以及用途的絕對是富有經驗的framework高手。
否則,一定需要一個案例來闡釋。假設我們有這樣一個layout,非常典型的

 
  1. <com.test.LayoutView1 xmlns:android="http://schemas.android.com/apk/res/android"  
  2.     android:orientation="vertical" android:layout_width="fill_parent"  
  3.     android:layout_height="fill_parent">  
  4.     <com.test.LayoutView2  
  5.         android:orientation="vertical" android:layout_width="fill_parent"  
  6.         android:layout_height="fill_parent" android:gravity="center">  
  7.         <com.test.MyTextView  
  8.             android:layout_width="wrap_content"   android:layout_height="wrap_content"  
  9.       />  
  10.     </com.test.LayoutView2>  
  11. </com.test.LayoutView1>

用一個樣本圖來解釋這個layout:


通常外圍的layoutview1,layoutview2,只是布局的容器不需要響應觸屏的點擊事件,僅僅Mytextview需要相應點擊。但這隻是一般情況,一些特殊的布局可能外圍容器也要響應,甚至不讓裡面的mytextview去響應。更有特殊的情況是,動態更換響應對象。
那麼首先看一下預設的觸屏事件的在兩個函數之間的傳遞流程。如:

如果僅僅想讓MyTextView來響應觸屏事件,讓MyTextView的OnTouchEvent返回true,那麼事件流就變成如,可以看到layoutview1,layoutview2已經不能進入OnTouchEvent:

另外一種情況,就是外圍容器想獨自處理觸屏事件,那麼就應該在相應的onInterceptTouchEvent函數中返回true,表示要截獲觸屏事件,比如layoutview1作截獲處理,處理流變成如:

以此類推,我們可以得到各種具體的情況,整個layout的view類層次中都有機會截獲,而且能看出來外圍的容器view具有優先截獲權。

當我們去做一些相對來講具有更複雜的觸屏互動效果的應用時候,經常需要動態變更touch event的處理對象,比如launcher待機案頭和主菜單(見),從滑動螢幕開始到停止滑動過程當中,只有外圍的容器view才可以處理touch event,否則就會誤點擊上面的應用表徵圖或者widget.反之在靜止不動的狀態下則需要能夠響應表徵圖(子view)的touch事件。摘取framework中abslistview代碼如下

 
  1. public boolean onInterceptTouchEvent(MotionEvent ev) {
  2.         int action = ev.getAction();
  3.         switch (action & MotionEvent.ACTION_MASK) {
  4.         case MotionEvent.ACTION_DOWN: {
  5.  
  6.             if (touchMode == TOUCH_MODE_FLING) {
  7.                 return true;  //fling狀態,截獲touch,因為在滑動狀態,不讓子view處理
  8.             }
  9.             break;
  10.         }
  11.         case MotionEvent.ACTION_MOVE: {
  12.             switch (mTouchMode) {
  13.             case TOUCH_MODE_DOWN:
  14.                 final int pointerIndex = ev.findPointerIndex(mActivePointerId);
  15.                 final int y = (int) ev.getY(pointerIndex);
  16.                 if (startScrollIfNeeded(y - mMotionY)) {
  17.                     return true;//開始滑動狀態,截獲touch事件,不讓子view處理
  18.                 }
  19.                 break;
  20.             }
  21.             break;
  22.         }
  23. }

總結:

僅僅通過概覽性的官方文檔是很難理解onInterceptTouchEvent函數的用途的,只有通過演繹這個抽象的規則,配以圖文才能擷取這個重要的知識。很顯然,預設是返回false,不做截獲。返回true之後,事件流的後端控制項就沒有機會處理touch事件了,把預設的事件流中每個處理函數看作一個節點,這個節點只要返回true, 後續的事件就被截止了,這樣想就很好理解。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.