2014-08-27 28 views
0

要求:確保itemLookup僅在按鈕被保持至少1秒後才執行。當按鈕被保持3秒時停止按鈕事件,因此用於查找的記錄不會包含不必要的數據。Android:觸發MotionEvent.ACTION_CANCEL

  • 問題:MotionEvent.ACTION_CANCEL即使調試確認TableLayoutForInterceptonInterceptTouchEvent被調用之前MainActivity「稱爲s OnTouchListener事件,預期不會被調用。也許我不明白onInterceptTouchEvent的目的?我已看過有關此事的其他帖子,但所有人都在處理刷卡或拖動事件,而不是取消按鈕按。也許這不可行?
  • 代碼:僅顯示MainActivity的相關部分,以及完整的TableLayoutForIntercept類,當然還有<com.company.myapplication.TableLayoutForIntercept></com.company.myapplication.TableLayoutForIntercept>標記環繞着我的xml佈局。

    public class MainActivity extends Activity { 
    
        //... 
    
        DateTime recordingStartedTime; 
        DateTime recordingEndedTime; 
        boolean buttonHeldLongEnough = false; 
    
        PackageManager pm = getPackageManager(); 
        boolean micPresent = pm.hasSystemFeature(PackageManager.FEATURE_MICROPHONE); 
    
        if (micPresent) { 
         recordBtn.setOnTouchListener(new View.OnTouchListener() { 
    
          @Override 
          public boolean onTouch(View recordView, MotionEvent recordEvent) { 
    
           switch (recordEvent.getAction()) { 
    
            case MotionEvent.ACTION_DOWN: 
             // Try to record audio 
             try { 
              recordingOff.setVisibility(View.INVISIBLE); 
              recordingOn.setVisibility(View.VISIBLE); 
    
              recordingStartedTime = DateTime.now(); 
              constructPrepareStartRecording(); 
             } 
             catch (Exception ex) { 
              Log.e(MainActivity.class.getSimpleName(), "An unknown error occurred."); 
             } 
             return true; 
    
            case MotionEvent.ACTION_UP: 
             recordingOff.setVisibility(View.VISIBLE); 
             recordingOn.setVisibility(View.INVISIBLE); 
    
             recordingEndedTime = DateTime.now(); 
             Seconds seconds = Seconds.secondsBetween(recordingStartedTime, recordingEndedTime); 
             int secondsButtonHeld = seconds.getSeconds(); 
    
             // Button must have been held at least 1 second before running itemLookup 
             if (secondsButtonHeld > 0) { 
              buttonHeldLongEnough = true; 
             } 
             else { 
              buttonHeldLongEnough = false; 
             } 
    
             // Need to release resources regardless 
             stopReleaseResetRecording(); 
    
             if (buttonHeldLongEnough) { 
              itemLookup(); 
             } 
             return true; 
    
            case MotionEvent.ACTION_CANCEL: 
             // I think this is the event I have to trigger to halt the button press 
             boolean codeHasHitCancel = true; 
             return codeHasHitCancel; 
    
           } 
           return false; 
          } 
         }); 
        } 
        else { 
         toastTitle = "Unable To Record"; 
         toastMessage = "Device microphone not found."; 
         toast = new GenericCustomToast(); 
         toast.show(toastTitle, toastMessage, MainActivity.this); 
        } 
    
        //... 
    } 
    
    public class TableLayoutForIntercept extends TableLayout { 
    
        public TableLayoutForIntercept (Context context) { 
         super(context); 
        } 
    
        public TableLayoutForIntercept (Context context, AttributeSet attrs) { 
         super(context, attrs); 
        } 
    
        private CancelPressTask cancelPressTask = null; 
        private boolean stopTouchEvent = false; 
    
        @Override 
        public boolean onInterceptTouchEvent (MotionEvent event) { 
    
         final int action = event.getAction(); 
    
         switch (action) { 
    
          case MotionEvent.ACTION_DOWN: 
           stopTouchEvent = false; 
           cancelPressTask = new CancelPressTask(); 
           break; 
    
          case MotionEvent.ACTION_CANCEL: 
          case MotionEvent.ACTION_UP: 
           cancelPressTask.resetCancelPressTimer(); 
           cancelPressTask.stopCancelPressTimer(); 
           return stopTouchEvent; 
         } 
    
         return super.onInterceptTouchEvent(event); 
        } 
    
        @Override 
        public boolean onTouchEvent (MotionEvent event) { 
    
         if (!stopTouchEvent) { 
         return super.onTouchEvent(event); 
         } 
    
         return true; 
        } 
    
        private class CancelPressTask { 
    
         public final long CANCEL_PRESS_TIMEOUT = 3000; // 3 seconds 
    
         private Handler cancelPressHandler = new Handler(){ 
          public void handleMessage(Message msg) { 
          } 
         }; 
    
         private Runnable cancelPressCallback = new Runnable() { 
          @Override 
          public void run() { 
           stopTouchEvent = true; 
          } 
         }; 
    
         public void resetCancelPressTimer(){ 
          cancelPressHandler.removeCallbacks(cancelPressCallback); 
          cancelPressHandler.postDelayed(cancelPressCallback, CANCEL_PRESS_TIMEOUT); 
         } 
    
         public void stopCancelPressTimer(){ 
          cancelPressHandler.removeCallbacks(cancelPressCallback); 
         } 
        } 
    } 
    

回答

0

我想出了另一種方式來進行此事。而不是試圖觸發一個事件,我決定它而不是!下面的代碼將停止記錄,然後在3秒鐘後查找項目,無論用戶嘗試按下按鈕的時間長短。唯一的缺點是對於記錄太短(小於1秒)的記錄,它仍然需要全部3秒鐘通過吐司消息來通知用戶。但我願意接受這一點。

public class Main Activity extends Activity { 

     DateTime recordingStartedTime; 
     DateTime recordingEndedTime = null; 
     boolean buttonHeldLongEnough = false; 
     LimitRecordingTask limitRecordingTask; 

     PackageManager pm = getPackageManager(); 
     boolean micPresent = pm.hasSystemFeature(PackageManager.FEATURE_MICROPHONE); 

     if (micPresent) { 
      recordBtn.setOnTouchListener(new View.OnTouchListener() { 
       @Override 
       public boolean onTouch(View recordView, MotionEvent recordEvent) { 

        limitRecordingTask = new LimitRecordingTask(); 
        switch (recordEvent.getAction()) { 

         case MotionEvent.ACTION_DOWN: 
          // Try to record audio 
          try { 
           recordBtn.setBackgroundColor(Color.DKGRAY); 
           recordingOff.setVisibility(View.INVISIBLE); 
           recordingOn.setVisibility(View.VISIBLE); 

           recordingStartedTime = DateTime.now(); 
           constructPrepareStartRecording(); 
           limitRecordingTask.resetRecordingTimer(); 
          } 
          catch (Exception ex) { 
           Log.e(MainActivity.class.getSimpleName(), "An unknown error occurred."); 
           limitRecordingTask.stopRecordingTimer(); 
          } 
          return true; 

         case MotionEvent.ACTION_UP: 
          // After 3 seconds limitRecordingTask will 'steal' this event 
          recordBtn.setBackgroundResource(R.drawable.custom_button); 
          recordingOff.setVisibility(View.VISIBLE); 
          recordingOn.setVisibility(View.INVISIBLE); 

          recordingEndedTime = DateTime.now(); 
          Seconds seconds = Seconds.secondsBetween(recordingStartedTime, recordingEndedTime); 
          int secondsButtonHeld = Math.abs(seconds.getSeconds()); 

          if (secondsButtonHeld > 0) { 
           buttonHeldLongEnough = true; 
          } 
          else { 
           buttonHeldLongEnough = false; 
          } 
          return true; 
        } 
        return false; 
       } 
      }); 
     } 
     else { 
      toastTitle = "Unable To Record"; 
      toastMessage = "Device microphone not found."; 
      toast = new GenericCustomToast(); 
      toast.show(toastTitle, toastMessage, MainActivity.this); 
     } 

     private class LimitRecordingTask { 

      public final long RECORDING_TIMEOUT = 3000; // 3 seconds 

      private Handler limitRecordingHandler = new Handler(){ 
       public void handleMessage(Message msg) { 
       } 
      }; 

      private Runnable limitRecordingCallback = new Runnable() { 
       @Override 
       public void run() { 
        // 'Stolen' MotionEvent.ACTION_UP 
        recordBtn.setBackgroundResource(R.drawable.custom_button); 
        recordingOff.setVisibility(View.VISIBLE); 
        recordingOn.setVisibility(View.INVISIBLE); 

        if (recordingEndedTime == null) { 
         recordingEndedTime = DateTime.now(); 
        } 
        Seconds seconds = Seconds.secondsBetween(recordingStartedTime, recordingEndedTime); 
        int secondsButtonHeld = Math.abs(seconds.getSeconds()); 

        if (secondsButtonHeld > 0) { 
         buttonHeldLongEnough = true; 
        } 
        else { 
         buttonHeldLongEnough = false; 
        } 

        limitRecordingTask.stopRecordingTimer(); 

        stopReleaseResetRecording(); 
        itemLookup(); 
       } 
      }; 

      public void resetRecordingTimer(){ 
       limitRecordingHandler.removeCallbacks(limitRecordingCallback); 
       limitRecordingHandler.postDelayed(limitRecordingCallback, RECORDING_TIMEOUT); 
      } 

      public void stopRecordingTimer(){ 
       limitRecordingHandler.removeCallbacks(limitRecordingCallback); 
      } 
     } 
    }