I'm having a very similar issue described here, except instead of using ScaleAnimation, I'm allowing pinch zoom/pan in my RelativeLayout.
The zoom/panning works perfectly, but regardless of how my view is panned/zoomed, the clickable area does not change along with the visual representation. Here's what my dispatchTouchEvent looks like:
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if (mScaleGestureDetector != null && mGestureDetector != null) {
mScaleGestureDetector.onTouchEvent(ev);
mGestureDetector.onTouchEvent(ev);
}
final int action = ev.getAction();
switch (action & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN: {
final float x = ev.getX();
final float y = ev.getY();
mLastTouchX = x;
mLastTouchY = y;
mActivePointerId = ev.getPointerId(0);
break;
}
case MotionEvent.ACTION_MOVE: {
final int pointerIndex = ev.findPointerIndex(mActivePointerId);
final float x = ev.getX(pointerIndex);
final float y = ev.getY(pointerIndex);
// Only move if the ScaleGestureDetector isn't processing a gesture.
if (!mScaleGestureDetector.isInProgress() && mScaleFactor > 1f) {
final float dx = x - mLastTouchX;
final float dy = y - mLastTouchY;
float newPosX = mPosX + dx;
float newPosY = mPosY + dy;
if (isCoordinateInBound(newPosX, mScreenSize.x))
mPosX = newPosX;
if (isCoordinateInBound(newPosY, mScreenSize.y))
mPosY = newPosY;
invalidate();
}
mLastTouchX = x;
mLastTouchY = y;
break;
}
case MotionEvent.ACTION_UP: {
mActivePointerId = INVALID_POINTER_ID;
break;
}
case MotionEvent.ACTION_CANCEL: {
mActivePointerId = INVALID_POINTER_ID;
break;
}
case MotionEvent.ACTION_POINTER_UP: {
final int pointerIndex = (ev.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK)
>> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
final int pointerId = ev.getPointerId(pointerIndex);
if (pointerId == mActivePointerId) {
final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
mLastTouchX = ev.getX(newPointerIndex);
mLastTouchY = ev.getY(newPointerIndex);
mActivePointerId = ev.getPointerId(newPointerIndex);
}
break;
}
}
return super.dispatchTouchEvent(ev);
}
and my dispatchDraw:
protected void dispatchDraw(Canvas canvas) {
canvas.save(Canvas.MATRIX_SAVE_FLAG);
canvas.translate(mPosX, mPosY);
canvas.scale(mScaleFactor, mScaleFactor);
super.dispatchDraw(canvas);
canvas.restore();
}
How do you modify the clickable area accordingly to modified scale/transformation of canvas?
Since you are already onverriding dispatchTouchEvent
, you can try this:
MotionEvent
by considering the current zoom/pan transformation; you can create a new MotionEvent
(let's call it FakeMotionEvent) by applying the reverse zoom/pan transformation to the original MotionEvent
m.View
v; this means the user is touching in a position which represents the user-visibile position of v. MotionEvent
and invoke v.dispatchTouchEvent(m);
TIP: You can use the method below to evaluate if a MotionEvent
intercepts a View
with a certain degree of tolerance:
private boolean intercept(MotionEvent ev, View view, float boundingBoxTolerance){
if (boundingBoxTolerance < 1.0f) {
boundingBoxTolerance = 1.0f;
}
try {
if (ev != null && view != null) {
int coords[] = new int[2];
view.getLocationOnScreen(coords);
if (ev.getRawX() >= ((float)coords[0]) / boundingBoxTolerance && ev.getRawX() <= coords[0] + ((float) view.getWidth()) * boundingBoxTolerance) {
if(ev.getRawY() >= ((float)coords[1]) / boundingBoxTolerance && ev.getRawY() <= coords[1] + ((float) view.getHeight()) * boundingBoxTolerance)
return true;
}
}
}
catch (Exception e) {}
return false;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With