Some time ago, there was a requirement that a 200 * 200 view could be dragged and clicked or jumped. Drag implementations naturally think of touch events that listen to views, and set the position of views when moving. The code is roughly as follows:
mDraggableView.setOnTouchListener(new View.OnTouchListener() { float dX; float dY; @Override public boolean onTouch(View view, MotionEvent event) { switch (event.getActionMasked()) { case MotionEvent.ACTION_DOWN: dX = view.getX() - event.getRawX(); dY = view.getY() - event.getRawY(); break; case MotionEvent.ACTION_MOVE: view.setX(event.getRawX() + dX); view.setY(event.getRawY() + dY); break; default: return false; } return true; } });
The click is done when the finger is raised, that is, when the ACTION_UP event is called back. If the last callback event is ACTION_DOWN, it is determined to be a click event, not a drag. The code is roughly as follows:
mDraggableView.setOnTouchListener(new View.OnTouchListener() { float dX; float dY; int lastAction; @Override public boolean onTouch(View view, MotionEvent event) { switch (event.getActionMasked()) { case MotionEvent.ACTION_DOWN: dX = view.getX() - event.getRawX(); dY = view.getY() - event.getRawY(); lastAction = MotionEvent.ACTION_DOWN; break; case MotionEvent.ACTION_MOVE: view.setX(event.getRawX() + dX); view.setY(event.getRawY() + dY); lastAction = MotionEvent.ACTION_MOVE; break; case MotionEvent.ACTION_UP: if (lastAction == MotionEvent.ACTION_DOWN) { // click event, do something } break; default: return false; } return true; } });
Test on your own development machine, normal, no problem. I thought it was all right, but the test made a bug, saying that it didn't work after clicking. So I found a mobile phone that can be rediscovered, and found that these phones do have bug. Obviously, it is only a very clear click event. The fingers are not moving at all. They still have callbacks of ACTION_MOVE events! But the displacement is small, only one or two pixels. To solve this problem, we need to identify the "drag" with only a few pixels moving as a click event, then add a distance. The code is as follows:
mDraggableView.setOnTouchListener(new View.OnTouchListener() { private static final int MIN_DISTANCE = 10; float initialX; float initialY; float dX; float dY; int lastAction; boolean farEnough = false; @Override public boolean onTouch(View view, MotionEvent event) { switch (event.getActionMasked()) { case MotionEvent.ACTION_DOWN: initialX = event.getRawX(); initialY = event.getRawY(); dX = view.getX() - event.getRawX(); dY = view.getY() - event.getRawY(); lastAction = MotionEvent.ACTION_DOWN; break; case MotionEvent.ACTION_MOVE: if (!farEnough) { if (Math.abs(event.getRawX() - initialX) > MIN_DISTANCE || Math.abs(event.getRawY() - initialY) > MIN_DISTANCE) { farEnough = true; } } view.setX(event.getRawX() + dX); view.setY(event.getRawY() + dY); lastAction = MotionEvent.ACTION_MOVE; break; case MotionEvent.ACTION_UP: if (lastAction == MotionEvent.ACTION_DOWN || (lastAction == MotionEvent.ACTION_MOVE && !farEnough)) { // click event, do something } farEnough = false; break; default: return false; } return true; } });