11

So I think I have a very simple issue but I can't seem to figure it out.

I have an ImageView and I am using it's setOnTouchListener method (OnTouch).

How can I differentiate between the ACTION_DOWN event and ACTION_MOVE event?

Even when I just click (touch) on the ImageView, ACTION_MOVE event gets called.

My goal is to open something(do anything) when the user clicks on it and move it when user holds it and moves it.

private int initialX;
private int initialY;
private float initialTouchX;
private float initialTouchY;

@Override
public boolean onTouch(View v, MotionEvent event) {
    switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            initialX = params.x;
            initialY = params.y;
            initialTouchX = event.getRawX();
            initialTouchY = event.getRawY();
            return true;
       case MotionEvent.ACTION_UP:
           return true;
       case MotionEvent.ACTION_MOVE:
           params.x = initialX + (int) (event.getRawX() - initialTouchX);
           params.y = initialY + (int) (event.getRawY() - initialTouchY);
           mWindowManager.updateViewLayout(mImgFloatingView, params);

           // Log.d("Params", "X: " + params.x + ".  Y: " + params.y + ".");

          if(params.x == initialX && params.y == initialY) {
              Toast.makeText(getBaseContext(), "Test", Toast.LENGTH_SHORT).show();
          }

          return true;
      }
      return false;
}
Limon Monte
  • 52,539
  • 45
  • 182
  • 213
ᴛʜᴇᴘᴀᴛᴇʟ
  • 4,466
  • 5
  • 39
  • 73
  • ACTION_DOWN is called when you first put your finger on the screen. Then if you keep your finger on the screen and start to move it, ACTION_MOVE is called – yrazlik Sep 11 '15 at 19:20
  • I understand that but my issue is that when I just tap on the `ImageView`, first ACTION_DOWN gets called and then ACTION_MOVE. That happens even when I only just tap (click), not move. Why is that? – ᴛʜᴇᴘᴀᴛᴇʟ Sep 12 '15 at 17:40

2 Answers2

8

As others have said, ACTION_MOVE is called along with ACTION_DOWN because of the sensitivity of the device and the inherent unsensitivity of big fingers. This is known as touch slop. The results you want can be obtained by adjusting the thresholds for time and distance moved. Alternatively, you could use a gesture detector.

OnTouch MotionEvent Actions

Based on the title of the question, I came here looking for a quick reference for the onTouch MotionEvent actions. So here is a snippet copied from the documentation:

@Override
public boolean onTouchEvent(MotionEvent event){

    int action = event.getActionMasked();

    switch(action) {
        case (MotionEvent.ACTION_DOWN) :
            Log.d(DEBUG_TAG,"Action was DOWN");
            return true;
        case (MotionEvent.ACTION_MOVE) :
            Log.d(DEBUG_TAG,"Action was MOVE");
            return true;
        case (MotionEvent.ACTION_UP) :
            Log.d(DEBUG_TAG,"Action was UP");
            return true;
        case (MotionEvent.ACTION_CANCEL) :
            Log.d(DEBUG_TAG,"Action was CANCEL");
            return true;
        case (MotionEvent.ACTION_OUTSIDE) :
            Log.d(DEBUG_TAG,"Movement occurred outside bounds " +
                    "of current screen element");
            return true;
        default :
            return super.onTouchEvent(event);
    }
}

Notes:

  • The above code could be used in an activity or a subclassed view. If subclassing a view is not desired, then the same motion events can be tracked by adding an OnTouchListener to the view. (example also taken from the documentation)

      View myView = findViewById(R.id.my_view);
      myView.setOnTouchListener(new OnTouchListener() {
          public boolean onTouch(View v, MotionEvent event) {
              // ... Respond to touch events
              return true;
          }
      });
    
  • Difference between getAction() and getActionMasked()

  • Returning true means that future events will still be processed. So if you returned false for ACTION_DOWN then all other events (like move or up) would be ignored.

Further reading

  • Using Touch Gestures: This is a series of official lessons in the documentation. It is an essential read for understanding how to correctly handle touch events and gestures.
Suragch
  • 484,302
  • 314
  • 1,365
  • 1,393
1

What is happening is that View.OnTouchListener will send you ALL events. If you tap and move by only 1 pixel, it'll be registered as a ACTION_MOVE.

You will need to implement some logic to determine a 'hold' action - waiting 100ms or something similar - after which a 'drag' action can proceed. Before that time, it should just be a 'click' action.

zmarkan
  • 605
  • 5
  • 13