你在Android中遇到過哪些滑動沖突?

對于滑動沖突,相信安卓開發(fā)的人都會有這種體會:本來從網(wǎng)上下載的demo運行得好好的,但是只要出現(xiàn)滑動沖突,demo就無法正常工作了。許多開發(fā)者面對滑動沖突都會顯得束手無策,(包括小編)于是小編就趕緊到處學習方法,并整理了下面的滑動沖突類型及解決方法,希望對和小編一樣的初學者有幫助。

常見的沖突場景

  • 場景一:外部滑動方向和內(nèi)部滑動方向不一致
外部滑動方向和內(nèi)部滑動方向不一致

在主流應用中,幾乎都會出現(xiàn)這種效果:首頁可以通過左右滑動來切換頁面,而每個頁面內(nèi)部往往又是一個ListView,這種情形下是有滑動沖突的(但是ViewPager內(nèi)部處理了這種滑動沖突)

處理規(guī)則

—— 根據(jù)用戶滑動的方向決定讓內(nèi)部View還是外部View攔截點擊事件

  • 場景二:外部滑動方向和內(nèi)部滑動方向一致
外部滑動方向和內(nèi)部滑動方向一致

在這類場景里,可以想象父View可以通過上下滑動切換頁面,然而內(nèi)部還是一個ListView,當用戶滑動的時候系統(tǒng)不知道該將滑動事件分發(fā)給誰

處理規(guī)則

—— 根據(jù)業(yè)務的規(guī)定決定讓內(nèi)部View還是外部View攔截點擊事件

比如說上述例子,可以采用內(nèi)部攔截法,優(yōu)先將滑動事件交給內(nèi)部ListView處理,當ListView已經(jīng)到達頂部或者底部已經(jīng)無法再進行同方向的滑動時,就將滑動事件交回給外部View處理,實現(xiàn)換頁功能。

  • 場景三:上面兩種情況的嵌套
多種情況的嵌套沖突

這類場景也很常見,假如你的首頁是一個ViewPager,可以來回切換不同頁面,每個頁面中又有各自的ListView,然后其實還隱藏著一個SlidingMenu在左側(cè)。

處理規(guī)則

—— 根據(jù)業(yè)務的規(guī)定決定讓內(nèi)部View還是外部View攔截點擊事件

主要是最SlidingMenu的處理,業(yè)務上可以要求當用戶的向右滑動是從app最左側(cè)邊緣開始時才將事件交給SlidingMenu處理。其他部分可以跟第一個場景一樣。

常用解決方式

  • 外部攔截法 —— 點擊事件都先經(jīng)過父容器的攔截處理,如果父容器需要此事件就攔截,如果不需要此事件就不攔截。
    外部攔截需要重寫父容器的onInterceptTouchEvent方法,偽代碼如下:
public boolean onInterceptTouchEvent(MotionEvent event){
     boolean intercepted = false;
     int x = (int) event.getX();
     int y = (int) event.getY();
     switch (event.getAction()){
     case MotionEvent.ACTION_DOWN:{
          // 對于ACTION_DOWN這個事件,父容器必須返回false,因為父容 器一旦攔截了
          // ACTION_DOWN,后續(xù)的ACTION_MOVE和ACTION_UP也都會直接交由父容器處理
          intercepted = false;
          break;
     }
     case MotionEvent.ACTION_MOVE:{
          if (父容器需要當前點擊事件) {
               intercepted = true;
          } else {
               intercepted = false;
          }
          break;
     }
     case MotionEvent.ACTION_UP:{
          intercepted = false;
          break;
     }
     default:
          break;
     }
     mLastXIntercept = x;
     mLastYIntercept = y;
     return intercepted;
}
  • 內(nèi)部攔截法 —— 指父容器不攔截任何事件,所有的事件都傳遞給子元素,如果子元素需要此事件就直接消耗掉,否則就交由父容器進行處理。
    內(nèi)部攔截需要重寫子元素的dispatchTouchEvent方法,偽代碼如下:
public boolean dispatchTouchEvent(MotionEvent event){
     int x = (int) event.getX();
     int y = (int) event.getY();
     switch (event.getAction()){
     case MotionEvent.ACTION_DOWN:{
          parent.requestDisallowInterceptTouchEvent(true);
          break;
     }
     case MotionEvent.ACTION_MOVE:{
          int deltaX = x - mLastX;
          int deltxY = y - mLastY;
          if (父容器需要當前點擊事件) {
               parent.requestDisallowInterceptTouchEvent(false);
          } 
          break;
     }
     case MotionEvent.ACTION_UP:{
          break;
     }
     default:
          break;
     }
     mLastX = x;
     mLastY = y;
     return super.dispatchTouchEvent(event);
}

另外,父容器也要做如下修改:

public boolean onInterceptTouchEvent(MotionEvent event){
      int action = event.getAction();
      if (action == MotionEvent.ACTION_DOWN) {
          return false;
      } else {
          return true;
      }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容