2013-10-17 67 views
3

我遇到了這個問題,其中ACTION_CANCEL沒有被觸發,我在其他項目中實現了它,它工作正常。看起來ACTION_UP是在ACTION_DOWN之後調用的唯一的MotionEvent。一旦我的手指不在視圖中或屏幕外,我想要觸發ACTION_CANCELMotionEvent.ACTION_CANCEL在onTouch過程中沒有觸發

示例場景:我點擊這是一個的LinearLayout順便說一句,在ACTION_DOWN其背景變爲「點擊/變暗」的圖像版本,並且在ACTION_UP被觸發其背景變回默認的圖像僅在視圖手指位於LinearLayout內。現在的問題是,當我按下它並將手指放在屏幕上時,將手指拖出LinearLayout,ACTION_UP仍然不應該觸發。

這裏是我的代碼:

dimView.setOnTouchListener(new OnTouchListener() { 
     public boolean onTouch(final View view, 
       final MotionEvent motionEvent) { 
      if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) { 
       Log.d("TAG", "DOWN"); 
       return true; 
      } else if (motionEvent.getAction() == MotionEvent.ACTION_UP) { 
       Log.d("TAG", "UP"); 
       return true; 
      } else if (motionEvent.getAction() == MotionEvent.ACTION_CANCEL) { 
       Log.d("TAG", "CANCEL"); 
       return true; 
      } 
      return false; 
     } 
    }); 

其中:dimView是LinearLayout中

回答

1
Override dispatchTouchEvent method maybe deal with it; 

dimView.setOnTouchListener(新OnTouchListener(){

 @Override 
     public boolean onTouch(View v, MotionEvent event) { 
      // TODO Auto-generated method stub 
      // to call super touch method 
      return false; 
     } 
    }); 

@Override 
public boolean dispatchTouchEvent(MotionEvent motionEvent) { 
    // TODO Auto-generated method stub 
    if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) { 
     Log.d("TAG", "DOWN"); 
     return true; 
    } else if (motionEvent.getAction() == MotionEvent.ACTION_UP) { 
     Log.d("TAG", "UP"); 
     return true; 
    } else if (motionEvent.getAction() == MotionEvent.ACTION_CANCEL) { 
     Log.d("TAG", "CANCEL"); 
     return true; 
    } 
    return super.dispatchTouchEvent(motionEvent); 
} 
+0

儘管如此,在測試過程中'MotionEvent.ACTION_CANCEL'仍然沒有被觸發。 –

8

我已經調試這很長一段時間,這讓我很困擾,因爲這是非常隨機的,然後我測試了我的代碼ces,並意識到隨着Android 4.2改變了API的實現。 預期的行爲和代碼在Android 4.1.2上工作得很好(在Galaxy Tab 2上測試過),但是您描述的bug可以在Nexus 7(Android 4.2)上看到。 顯然,Android改變了MotionEvent在API 17中的處理方式。

錯誤未發生時的一種特殊情況是視圖位於GroupLayout下的ScrollView下。當滾動可能時,ACTION_CANCEL被觸發。但是,當沒有滾動是可能的錯誤仍然存​​在。

起初,我嘗試了將OnClickListenerOnTouchListener合併,以便最後一個可以處理動畫但無濟於事。從父母派遣活動也不起作用。

一個解決辦法是捕捉ACTION_MOVE事件和檢查手指位於使用v.getX()v.getY()並將它們與event.getX()event.getY()體面視圖的邊界之外。全局布爾變量(isOutside)可用於存儲最新信息。在啓動ACTION_UP之前,您可以檢查最新狀態isOutside並相應地執行動畫和操作。您也可以根據是否捕獲事件返回true或false。

更新:在挖了一點後,我發現這個解決方案: Android: Detect if user touches and drags out of button region?並編譯了這段代碼。這個想法是相同的,只不過它創建了一個矩形並檢查事件邊界是否在視圖的矩形內。

someView.setOnTouchListener(new View.OnTouchListener() { 

       private Rect rect; 

       @Override 
       public boolean onTouch(View v, MotionEvent event) { 
        Log.d(TAG,"Touched: "+event.getAction()); 
        if (event.getAction() == MotionEvent.ACTION_DOWN) { 
         Log.d(TAG,"ACTION_DOWN"); 
         animateImageButtonOnClick(v, event); 
         rect = new Rect(v.getLeft(), v.getTop(), v.getRight(), v.getBottom()); 
        } 

        if (event.getAction() == MotionEvent.ACTION_UP) { 
         Log.d(TAG,"ACTION_UP"); 
         if (!rect.contains(v.getLeft() + (int) event.getX(), v.getTop() + (int) event.getY())) { 
          Log.d(TAG,"ACTION_UP - outside"); 
          animateImageButtonOnRelease(v, event); 
         } else { 
          Log.d(TAG,"ACTION_UP - inside"); 
          // do your stuff here 
         } 
        } 

        if(event.getAction() == MotionEvent.ACTION_MOVE){ 
         if(!rect.contains(v.getLeft() + (int) event.getX(), v.getTop() + (int) event.getY())){ 
          animateImageButtonOnReleaseWithLowDuration(v, event); 
         } 
        } 

        if (event.getAction() == MotionEvent.ACTION_CANCEL){ 
         Log.d(TAG,"ACTION_CANCEL"); 
         animateImageButtonOnRelease(v, event); 
         return true; 
        } 

        return true; 
       } 
      }); 
+0

非常好!有用! – Itay