0

I know that a onLongTouchListener does not exists, so I'm trying to do my own version of it, I can't use onLongClickListener because I really need the touch coordinates. My code is bellow:

touchImageView.setOnTouchListener(new View.OnTouchListener() {
      @Override
      public boolean onTouch(View view, final MotionEvent motionEvent) {

          CountDownTimer counter = new CountDownTimer(500, 1) {
              public void onTick(long millisUntilFinished) {
                  System.out.println("REMAINING: "+(millisUntilFinished));
              }

              public void onFinish() {
                  System.out.println("IT'S OVER");
              }
          };

          if (motionEvent.getAction() == MotionEvent.ACTION_DOWN){
              counter.start();
          } else if( motionEvent.getAction() == MotionEvent.ACTION_UP){
              counter.cancel();
          }

          return true;
      }
  });

The problem: the counter is starting when I put my finger on the screen but it's not cancelling when I lift my finger as I was expecting with:

else if( motionEvent.getAction() == MotionEvent.ACTION_UP){
  counter.cancel();
}

Can you guys help me please?

EDIT:

After following the comments and the answer, it's working now:

final CountDownTimer counter;
        counter = new CountDownTimer(500,1) {
            @Override
            public void onTick(long l) {
                System.out.println("REMAINING "+l);
            }

            @Override
            public void onFinish() {
                System.out.println("IT'S OVER");
                Vibrator v = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                    v.vibrate(VibrationEffect.createOneShot(100, VibrationEffect.DEFAULT_AMPLITUDE));
                }
            }
        };

        touchImageView.setOnTouchListener(new View.OnTouchListener() {
            CountDownTimer c = counter;
            @Override
            public boolean onTouch(View view, MotionEvent motionEvent) {
                if (motionEvent.getAction() == MotionEvent.ACTION_DOWN){
                    c.start();
                }
                if (motionEvent.getAction() == MotionEvent.ACTION_UP){
                    c.cancel();
                }

                return true;
            }
        });
zampnrs
  • 345
  • 1
  • 2
  • 13
  • 1
    because when you lift your finger off, you are starting a second counter, and cancelling that one. The first counter is still going. – Blundell Jul 23 '19 at 20:03
  • 1
    To add to the below answer, onTouch() is called 2 times **separately**, once for ACTION_DOWN and once for ACTION_UP. Your code assumes that once ACTION_DOWN has started, the function will only end at ACTION_UP which is not the case. – Zohaib Amir Jul 23 '19 at 21:04
  • Thank you guys, I solved it following what you said! I'll post an edit version of the code in my question – zampnrs Jul 24 '19 at 12:20

1 Answers1

6

This is happening because you are not cancelling the same counter. When onTouch is triggered the first time (ACTION_DOWN), you construct a counter and start it. When onTouch is triggered the second time (ACTION_UP), you construct a new counter and cancel it. You are starting one counter and cancelling a completely different one.

You will need to maintain a counter outside of the onTouch listener or ensure that you are indeed cancelling the correct counter some other way.

michael
  • 463
  • 3
  • 9
  • 1
    "ensure that you are indeed cancelling the correct counter some other way" there is no other way because in current code the object reference gets overwritten so now there is no reference to the one that was started. Putting it outside is the only option. – Zohaib Amir Jul 23 '19 at 21:01
  • 1
    Thanks a lot! I could solve it following what you said. I'll post an edit version of the code in my question – zampnrs Jul 24 '19 at 12:21