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