Skip to content Skip to sidebar Skip to footer

Scalegesturedetector Not Working For View Within Fragment Or Viewgroup Layout On Ics And Below

My application makes use of the support package to implement Fragments on 2.2 upwards. I have a View subclass (let's call it ZoomableView) that makes use of ScaleGestureDetector to

Solution 1:

From inspecting the ScaleGestureDetector source code on grepcode, I see that Jellybean versions of ScaleGestureDetector do not make use of getRawX() and getRawY() methods of the MotionEvent. However, the earlier versions (Froyo, ICS etc) do make use of getRawX() and getRawY() for the purpose of slop calculation. This is where the problem is, because it means that the scale detector won't work if the target View doesn't have its top left near 0,0.

I got the ScaleGestureDetector to work on my custom ZoomView, even with it being placed on the right or bottom, by simply doing this within onTouchEvent():

event.setLocation(event.getRawX(), event.getRawY());    
mScaleDetector.onTouchEvent(event);

That causes adjustment of the MotionEvent's internal offset variables such that the getX/Y and getRawX/Y methods now return exactly the same value. This prevents the slop calculation failing. The scale detector of course works with relative values and so it doesn't matter about the absolute values of X / Y. If you have further code that relies on the absolute values, you could do what I did to restore them after:

float originalY = event.getY();
    float originalX = event.getX();     
    event.setLocation(event.getRawX(), event.getRawY());
    mScaleDetector.onTouchEvent(event);
    event.setLocation(originalX, originalY);

Furthermore, if I want to place my Fragment that contains a MapView on the bottom or right, I am already using a custom subclass of MapView anyway and so I just added this:

public boolean onTouchEvent(MotionEvent event) {

    // Work around required for ScaleGestureDetector.// Before calling the scale detector, perform a work-around that is needed for earlier APIs (I suspect// ICS and below, judging from inspection of ScaleGestureDetector) to make the MotionEvent give the // same values for getY / getRawY and getX / getRawX. Wildly different values, caused by the View// being nowhere near the screen origin (i.e. the View is on the right or the bottom) means the // detector doesn't work. 

    event.setLocation(event.getRawX() - getLeft(), event.getRawY() - getTop());
    return super.onTouchEvent(event);
}

Now, my MapView will pinch scale properly too, no matter where its Fragment is placed. (By the way - totally OT to this question, but in case anyone is wondering, I placed a MapView into a Fragment successfully using the LocalActivityManager solution as given on StackOverflow). EDIT: Actually, something is not 100% right: The map doesn't zoom around the center of the pinch gesture. I think it's to do with the ActionBar / notification bar height not being compensated for in the getTop().

Post a Comment for "Scalegesturedetector Not Working For View Within Fragment Or Viewgroup Layout On Ics And Below"