David
David

Reputation: 39

OnLongClick button listener android

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

Answers (1)

CrepeGoat
CrepeGoat

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:

Abbreviated

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

Full Rewrite

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

Related Questions