Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android OnTouch MotionEvent Actions

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;
}
like image 555
ᴛʜᴇᴘᴀᴛᴇʟ Avatar asked Sep 11 '15 14:09

ᴛʜᴇᴘᴀᴛᴇʟ


People also ask

What is Action_up and Action_down?

It doesn't mean a gesture like swipe down it means that user touched the screen (finger down, the touch or gesture just started). Now you need to catch MotionEvent.ACTION_UP (finger up, gesture or touch ends here) and decide if there was a gesture you need. http://developer.android.com/training/gestures/detector.html.

How do you make a motion event on android?

Use the getPointerId(int) method to obtain a pointer id to track pointers across motion events in a gesture. Then for successive motion events, use the findPointerIndex(int) method to obtain the pointer index for a given pointer id in that motion event.

How are Android touch events delivered?

The touch event is passed in as a MotionEvent , which contains the x,y coordinates, time, type of event, and other information. The touch event is sent to the Window's superDispatchTouchEvent() . Window is an abstract class. The actual implementation is PhoneWindow .

What is motion event?

Motion Event Explanation Motion events describe movements in terms of an action code and a set of axis values. The action code specifies the state change that occurred such as a pointer going down or up. The axis values describe the position and other movement properties.


2 Answers

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.
like image 159
Suragch Avatar answered Oct 18 '22 14:10

Suragch


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.

like image 23
zmarkan Avatar answered Oct 18 '22 12:10

zmarkan