javaandroidtouchimageview

CountDownTimer not cancelled on MotionEvent.ACTION_UP after starting it in ACTION_DOWN


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

Solution

  • 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.