【问题标题】:Android: Triggering MotionEvent.ACTION_CANCELAndroid:触发 MotionEvent.ACTION_CANCEL
【发布时间】:2014-08-27 20:41:08
【问题描述】:

要求:确保itemLookup 仅在按住按钮至少 1 秒时才执行。按住按钮 3 秒后停止按钮事件,因此用于查找的记录不会包含不必要的数据。

  • 问题:MotionEvent.ACTION_CANCEL 从未被调用,即使调试确认 TableLayoutForInterceptonInterceptTouchEvent 在调用 MainActivityOnTouchListener 事件之前被调用,正如预期的那样。也许我不明白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);
            }
        }
    }
    

【问题讨论】:

    标签: java android button touch-event motionevent


    【解决方案1】:

    我想出了另一种方法来解决这个问题。我没有尝试触发一个事件,而是决定窃取它!下面的代码将停止录制,然后在 3 秒后进行项目查找,无论用户尝试按住按钮多长时间。唯一的问题是对于太短(少于 1 秒)的录音,仍然需要整整 3 秒才能通过 toast 消息通知用户。但我愿意接受。

        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);
                }
            }
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-01-27
      • 1970-01-01
      • 2023-03-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-30
      相关资源
      最近更新 更多