[英]Android: Triggering MotionEvent.ACTION_CANCEL
The Requirements: Ensure that itemLookup
is only performed if the button has been held for at least 1 second. 要求:确保仅在按住按钮至少1秒钟后才执行itemLookup
。 Stop the button event when the button has been held for 3 seconds, so the recording used for the lookup will not contain unnecessary data. 按住按钮3秒钟后停止按钮事件,因此用于查找的记录将不包含不必要的数据。
MotionEvent.ACTION_CANCEL
is never called even though debugging confirms that TableLayoutForIntercept
's onInterceptTouchEvent
is being called before MainActivity
's OnTouchListener
event is called, as expected. 问题: MotionEvent.ACTION_CANCEL
即使调试确认是从来没有所谓的TableLayoutForIntercept
的onInterceptTouchEvent
被调用之前MainActivity
的OnTouchListener
事件被称为,符合市场预期。 Perhaps I am not understanding the purpose of onInterceptTouchEvent
? 也许我不了解onInterceptTouchEvent
的目的? I've looked at other posts about this matter, but all of them are dealing with swipe or drag events, not cancelling a button press . 我看过有关此问题的其他帖子,但是所有这些帖子都在处理滑动或拖动事件,而不是取消按钮的按下 。 Perhaps this can't be done? 也许这不能做到? The Code: Only the relevant parts of MainActivity
are shown, along with the full TableLayoutForIntercept
class, and of course <com.company.myapplication.TableLayoutForIntercept></com.company.myapplication.TableLayoutForIntercept>
tags surround my xml layout. 代码:仅显示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); } } }
I figured out another way to go about this. 我想出了另一种解决方法。 Instead of trying to trigger an event, I decided to steal it instead! 我没有尝试触发事件,而是决定窃取它! The below code will stop the recording, then do the item look-up after 3 seconds has elapsed, no matter how long the user tries to hold the button down for. 下面的代码将停止录制,然后无论用户尝试按住按钮多长时间,都会在3秒钟后查找项目。 The only catch is for recordings that are too short (less than 1 second) it will still take the full 3 seconds to notify the user via toast message. 唯一的不足是录制时间太短(少于1秒),仍然需要整整3秒钟通过Toast消息通知用户。 But I'm willing to live with that. 但我愿意忍受。
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);
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.