Issue
I have programmed a simple test app, where Drawable
objects (the yellow translucent tiles at the screenshot below) can be dragged around on a scrollable and scallable (by using Matrix) Canvas:
Here is the code handling dragging:
private Drawable mDragged = null;
private float mPrevX;
private float mPrevY;
public boolean onTouchEvent(MotionEvent e) {
// Convert touch coordinates to Canvas coordinates
float[] point = new float[] {e.getX(), e.getY()};
Matrix inverse = new Matrix();
mMatrix.invert(inverse);
inverse.mapPoints(point);
float x = point[0];
float y = point[1];
switch (e.getAction()) {
case MotionEvent.ACTION_DOWN:
Drawable tile = hitTest(x, y);
if (tile != null) {
mDragged = tile;
mPrevX = x;
mPrevY = y;
return true;
}
break;
case MotionEvent.ACTION_MOVE:
if (mDragged != null) {
float dX = x - mPrevX;
float dY = y - mPrevY;
mPrevX = x;
mPrevY = y;
Rect rect = mDragged.copyBounds();
rect.left += dX;
rect.top += dY;
rect.right = rect.left + mDragged.getIntrinsicWidth();
rect.bottom = rect.top + mDragged.getIntrinsicHeight();
mDragged.setBounds(rect);
invalidate();
return true;
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
if (mDragged != null) {
mDragged = null;
return true;
}
break;
}
// Handle Canvas scrolling and scaling here
}
It works, but I have a problem - when I touch a tile and then drag it around - the tile departs from my finger (or from my mouse pointer, when using Android emulator).
I.e. the distance between the dragged Drawable
and the finger (or mouse pointer - as can be seen on the above screenshot) increases, while it is being dragged around.
This can't be a multi-touch related issue - because there is only single touch on the emulator.
What is the root cause here?
Solution
Just a hunch here, but it's probably due to two things being compounded together:
- Your coordinates are
float
values, but theRect
consists ofint
values, which can cause some rounding issues - On each ACTION_MOVE event, you are adding the (potentially) rounded values, and changing the baseline (
mPrevX
&mPrevY
) instead of calculating the absolute distance from where you first started dragging
I would store the current position of the tile when dragging starts (including offset from the cursor position), and then base all the movement calculations off of that point.
Answered By - JstnPwll
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.