Android中點擊事件的處理解析及常見問題


      當我們手指按下時,Android采用層層傳遞-冒泡的方式處理點擊事件。例如,現在公司來了個小項目,老板一看分配給經理做,經理一看分配給小組長,小組長一看好簡單,分配給組員。如果在這個傳遞過程中(也就是還為分配到最底部時),某一層覺得我來負責這個比較好的話就會攔截掉這個消息,然后把它處理了,下面的就收不到有消息的這個通知。如果一直到了底層的話,組員如果能完成,就完成它。如果不能完成,那么就報告給組長,說組長我做不來,邊學邊做要影響進度。組長一看我也做不來,就給經理,經理一看我也不會,就給老板。這樣也就一層層的傳遞了。 
      以上的意思也即:消息從上到下依次傳遞,如果在傳遞的過程中被攔截了就停止下傳。如果沒有被攔截,就一直傳遞到底部,如果底部不能夠消耗該消息,那么就又一層層的返回來,返給上層,直到被消耗或者是到達最頂層。在此過程中,存在三個重要的方法:

    dispathTouchEvent(MotionEvent ev)  
負責事件的分發,它的返回值就是表示是否消耗當前事件; onInterceptTouchEvent(MotionEvent ev)
用於判斷是否攔截該消息,如果當前View攔截了某個時間,那么在同一個事件序列中,此方法不會被再次調用。返回結果表示是否攔截當前事件 。 onTouchEvent(MotionEvent ev)
處理事件。返回結果表示是否消耗當前事件,如果不消耗,則在同一時間序列中,當前View無法再次接收到事件。

      對於一個根ViewGroup來說,點擊事件產生后,首先會傳遞給它,並調用它的dispath方法。如果這個ViewGroup的onIntercept方法返回true就表示它要攔截當前事件,false就表示不攔截,這個時候事件就會繼續傳遞給子元素,接着調用子元素的dispath方法,一直重復以上過程到事件被處理。

      下面介紹一下常見的問題及解決方法:

一、滑動沖突

     View的滑動沖突產生願意大概可以分為三種:

  • 外部滑動和內部滑動方向不一致
  • 外部滑動方向和內部滑動方向一致
  • 嵌套上面兩種情況

     比如說一個常見的,外部一個ListView,里面一個ScrollView,滑動時出現沖突?

此時一般是采用外部攔截法(即結合onInterceptTouchEvent、onTouchEvent來進行解決。具體方法如下:

   (1)外部攔截法

      外部攔截法就是指所有的點擊時間都經過父容器的攔截處理,如果父容器需要此事件就攔截,如果不需要此事件就不攔截。通過重寫父容器的onInterceptTouchEvent方法:

 case MotionEvent.ACTION_DOWN:
      intercepted = false;
      break;
 case MotionEvent.ACTION_MOVE:
     if(父類容器需要) {
        intercepted = true;
     } else {
        intercepted = false;
     }
     break;
  case MotionEvent.ACTION_UP:
       intercepted = false;
       break;
 return intercepted;

注:ACTION_DOWN事件父類容器就必須返回false,因為如果父類容器攔截了的話,后面的Move等所有事件都會直接由父類容器處理,就無法傳給子元素了。UP事件也要返回false,因為它本身來說沒有太多的意義,但是對於子元素就不同了,如果攔截了,那么子元素的onClick事件就無法觸發。

內部攔截法 
這種方法指的是父容器不攔截任何時間,所有的事件都傳遞給子元素,如果子元素需要此事件就直接消耗掉,否則就交給父容器進行處理。它需要配合requestDisallowInterceptTouchEvent方法才能正常工作。我們需要重寫子元素的dispatch方法。

    case MotionEvent.ACTION_DOWN:
    parent.requestDisallowInterceptTouchEvent(true);
    break;
    MotionEvent.ACTION_MOVE:
    if(父容器需要此類點擊事件) {
    parent.requestDisallowInterceptTouchEvent(false);
    }
    break;
    return super.dispatchTouchEvent(event);

這種方法的話父類容器需要默認攔截除了ACTION_DOWN以外的其他時間,這樣當子元素調用request方法的時候父元素才能繼續攔截所需的事件。

其他的 
      如果覺得上面兩個方式太復雜,看暈了,其實也可以自己根據項目的實際需要來指定自己的策略實現。例如根據你手指按的點的位置來判斷你當前觸碰的是哪個控件,以此來猜測用戶是否是要對這個控件進行操作。如果點擊的是空白的地方,就操作外部控件即可。

 ,具體可參考ViewPager中的滑動沖突


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM