Reputation: 39
Hello :) I am trying to detect when the user press a long click on the button and when he releases the long click so I am using this answer: https://stackoverflow.com/a/10746549/3953319 I don't know why but the LongClickListener is called twice to me, here is my code:
button1.setOnLongClickListener(new View.OnLongClickListener() {
public boolean onLongClick(View pView) {
TimeCounter = 0;
final Random rand = new Random();
time = rand.nextInt(7) + 1;
SecTime = time * 1000;
CountDownTimer2 = new CountDownTimer(SecTime, 1000) {
public void onTick(long millisUntilFinished) {
}
public void onFinish() {
mPlayer = MediaPlayer.create(MainActivity.this,
R.raw.windows_8_notify);
mPlayer.start();
t = new Thread() {
@Override
public void run() {
try {
while (!isInterrupted()) {
Thread.sleep(1);
runOnUiThread(new Runnable() {
@Override
public void run() {
TimeCounter++;
textview.setText("Your reaction time:"
+ TimeCounter + "MS");
}
});
}
} catch (InterruptedException e) {
}
}
};
t.start();
}
}.start();
isSpeakButtonLongPressed = true;
return true;
}
});
button1.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View pView, MotionEvent pEvent) {
pView.onTouchEvent(pEvent);
if (pEvent.getAction() == MotionEvent.ACTION_UP) {
if (isSpeakButtonLongPressed) {
if (mPlayer == null) {
textview.setText("You have released the button before the sound");
CountDownTimer2.cancel();
} else {
t.interrupt();
t = null;
OldScore = sharedpreferences.getInt("HighScore", 0);
if (TimeCounter < OldScore) {
Editor editor = sharedpreferences.edit();
editor.putInt("HighScore", TimeCounter);
editor.commit();
textview1.setText("Your new High Score:"
+ TimeCounter + "MS");
}
textview.setText("Your reaction time:"
+ TimeCounter + "MS");
mPlayer.pause();
mPlayer.reset();
mPlayer = null;
}
isSpeakButtonLongPressed = false;
}
}
return false;
}
});
I ran the application and when I long click the button I hear the "windows_8_notify" twice, why is that? is there any better way to do it?
Upvotes: 0
Views: 668
Reputation: 2515
I believe it is because in your onTouchListener
's onTouch
method, you call pView.onTouch(...)
, and then at the end, return false
. The return false
line indicates that your onTouchListener
has not handled the onTouch
event, so then it resorts to calling it's default onTouch
function, which is identical to your pView.onTouch(...)
call. However, the default function happens to also call your onLongClickListener
's onLongClick
method. Thus, it calls pView.onTouch(...)
twice, each time calling your onLongClickListener
's onLongClick
method.
SO. I believe you can avoid this if you return true
in the onTouch
method in appropriate cases. In my mind, it would look something like this:
button1.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View pView, MotionEvent pEvent) {
boolean longClickOccurred = pView.onTouchEvent(pEvent);
...
if (pEvent.getAction()...) {
if (isSpeakButtonLongPressed) {
...
longClickOccurred = true;
}
}
return longClickOccurred;
}
});
button1.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View pView, MotionEvent pEvent) {
boolean longClickOccurred = pView.onTouchEvent(pEvent);
if (pEvent.getAction() == MotionEvent.ACTION_UP) {
if (isSpeakButtonLongPressed) {
if (mPlayer == null) {
textview.setText("You have released the button before the sound");
CountDownTimer2.cancel();
} else {
t.interrupt();
t = null;
OldScore = sharedpreferences.getInt("HighScore", 0);
if (TimeCounter < OldScore) {
Editor editor = sharedpreferences.edit();
editor.putInt("HighScore", TimeCounter);
editor.commit();
textview1.setText("Your new High Score:"
+ TimeCounter + "MS");
}
textview.setText("Your reaction time:"
+ TimeCounter + "MS");
mPlayer.pause();
mPlayer.reset();
mPlayer = null;
}
isSpeakButtonLongPressed = false;
longClickOccurred = true;
}
}
return longClickOccurred;
}
});
This will(should) stop your button from recalling the pView.onTouchEvent(pEvent)
, without interfering with other click functions.
(In fact, I don't think you need the boolean variable isSpeakButtonLongPressed
, because its value is basically identical to longClickOccurred
when you assert that pEvent.getAction() == MotionEvent.ACTION_UP. UNLESS 1) you use isSpeakButtonLongPressed
outside of the onTouch
function, or 2) you have some other onClickListener
set or something like that, which will cause pView.onTouchEvent(pEvent)
to return true
when a long click has not occurred.)
Anyway, I hope the works/helps/was-not-a-convoluted-explanation. Good luck!
Upvotes: 3