11

I have a MapView in an activity and it works fine, the map shows, and it responds to taps, and I can extract the location easily. However this handler is also responding to the pinch-zoom, so if a user tries to pinch-zoom, the app responds as if they tapped (and it's very confusing for them).

How can I respond to taps on a MapView and only pick up single-taps, specifically ignoring pinch-zoom and double-taps?

Do I need to use OnTouchEvent() instead of OnTap()? If so how do I distinguish between the different touch events, and how do I access the GeoPoint?

Here's the code from inside my MapActivity:

class MapOverlay extends com.google.android.maps.Overlay
{
    @Override
    public boolean onTap(GeoPoint p, MapView map)
    {
        if ( p!=null )
        {
            // Do stuff with the geopoint
            return true;                                 // We handled the tap
        }
        else
        {
            return false;                                // We didn't handle the tap
        }
    }
}
Ollie C
  • 28,313
  • 34
  • 134
  • 217
  • You might be able to keep using onTap, which is designed to only respond when overlay items are tapped (as opposed to anywhere on the map), and still set a touch listener on the MapView to ignore pinch, like this: http://stackoverflow.com/questions/4626028/how-to-disable-pinch-in-android-mapview – Charlie Collins Jan 26 '11 at 16:33
  • Interestingly dragging the map is fine. so Drag doesn't fire onTap() but tap does (as expected) but also pinch & zoom. It's not what I would have expected. – Ollie C Jan 27 '11 at 19:17
  • I don't want to disable pinch & zoom, I want it to work, I just want my app to pick up the onTap as well. – Ollie C Jan 28 '11 at 21:31

1 Answers1

27

After much head-scratching and trying various approaches, this one is working well so far. The code follows the motion events. When we get an ACTION_DOWN event, it marks the isPinch flag as false (we don't know if it's a pinch or not yet), but as soon as we get a touch event (i.e. ACTION_MOVE) involving two fingers, isPinch is set to true, and so when the onTap() event fires, it can see if there was a pinch or not.

class MapOverlay extends com.google.android.maps.Overlay
{
private boolean   isPinch  =  false;

@Override
public boolean onTap(GeoPoint p, MapView map){
    if ( isPinch ){
        return false;
    }else{
        Log.i(TAG,"TAP!");
        if ( p!=null ){
            handleGeoPoint(p);
            return true;            // We handled the tap
        }else{
            return false;           // Null GeoPoint
        }
    }
}

@Override
public boolean onTouchEvent(MotionEvent e, MapView mapView)
{
    int fingers = e.getPointerCount();
    if( e.getAction()==MotionEvent.ACTION_DOWN ){
        isPinch=false;  // Touch DOWN, don't know if it's a pinch yet
    }
    if( e.getAction()==MotionEvent.ACTION_MOVE && fingers==2 ){
        isPinch=true;   // Two fingers, def a pinch
    }
    return super.onTouchEvent(e,mapView);
}

}
Rune
  • 698
  • 1
  • 7
  • 22
Ollie C
  • 28,313
  • 34
  • 134
  • 217