33

GoogleMap by default doesn't provide event for map drag start and drag stop. I have already reported that problem here.

I want to make custom handler that will use plain onTouch event and combine it with setOnCameraChangeListener.

However i failed to find how I can access onTouch event of GoogleMap object. It doesn't provide such callback.

I wonder how can i handle onTouch event for map in Google Map API v2?

Community
  • 1
  • 1
Alexey Zakharov
  • 24,694
  • 42
  • 126
  • 197

2 Answers2

41

Here is a possible workaround for determining drag start and drag end events:

You have to extend SupportMapFragment or MapFragment. In onCreateView() you have to wrap your MapView in a customized FrameLayout (in example below it is the class TouchableWrapper), in which you intercepts touch events and recognizes whether the map is tapped or not. If your onCameraChange gets called, just check whether the map view is pressed or not (in example below this is the variable mMapIsTouched).

Example code:

UPDATE 1:

  • return original created view in getView()
  • use dispatchTouchEvent() instead of onInterceptTouchEvent()

Customized FrameLayout:

private class TouchableWrapper extends FrameLayout {
    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
    switch (ev.getAction()) {
        case MotionEvent.ACTION_DOWN:
        mMapIsTouched = true;
        break;

    case MotionEvent.ACTION_UP:
        mMapIsTouched = false;
        break;
        }

        return super.dispatchTouchEvent(ev);
    }
    }

In your customized MapFragment:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {
    mOriginalContentView = super.onCreateView(inflater, parent, savedInstanceState);

    mTouchView = new TouchableWrapper(getActivity());
    mTouchView.addView(mOriginalContentView);

    return mTouchView;
}

@Override
public View getView() {
    return mOriginalContentView;
}

In your camera change callback method:

private final OnCameraChangeListener mOnCameraChangeListener = new OnCameraChangeListener() {
    @Override
    public void onCameraChange(CameraPosition cameraPosition) {
        if (!mMapIsTouched) {
            refreshClustering(false);
        }
    }
};
lambda
  • 3,295
  • 1
  • 26
  • 32
AZ13
  • 14,397
  • 5
  • 35
  • 31
  • 1
    Hey @Alexey Zakharov, please have also a look into the Thread at Google Maps issue tracker: http://code.google.com/p/gmaps-api-issues/issues/detail?id=4636&q=apitype%3DAndroid2&sort=-modified&colspec=ID%20Type%20Status%20Introduced%20Fixed%20Summary%20Stars%20ApiType%20Internal%20Modified – AZ13 Dec 07 '12 at 08:22
  • @Alexey Zakharov i tried it but i get errors: the first error is on getActivity. could you post your customized MapFragment class declaration? (or entire code) – Gaucho Dec 30 '12 at 16:12
  • you need to extend SupportMapFragment or MapFragment. – AZ13 Jan 09 '13 at 17:19
  • Dear @AZ13 , I wrote it down this way but i get errors on getActivity(the code doesn't compiles): public class MyMapFragment extends MapFragment{ public View mOriginalContentView; public TouchableWrapper mTouchView; @ Override public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) { mOriginalContentView = super.onCreateView(inflater, parent, savedInstanceState); mTouchView = new TouchableWrapper(getActivity()); ...continues.. – Gaucho Jan 10 '13 at 17:38
  • 1
    @AZ13, I did use your solution as a base, but I improved on it by using a custom listener instead of a public static variable. Please see my solution below. Also, in your case using the mMapIsTouched boolean in the OnCameraChangeListener does not work most of the time, since the OnCameraChangeListener more often than not fires before the boolean value is updated, thus your code in the if will never fire off. – Dimitar Darazhanski Apr 09 '13 at 16:47
  • 1
    @AZ13, Awesome answer. If you or anyone else is interested, I just created a library for managing a draggable overlay box using this answer as inspiration. Find it here: https://github.com/mattlogan/DraggableOverlayBox – Matt Logan May 20 '14 at 17:05
  • Hi @MattLogan Please check your github link and please provide a correct one. – Subho Jun 18 '16 at 12:29
7

There is a simpler way to do this, handle your cases on onCameraMoveStarted listener like this

Below the code snippet

@Override
public void onCameraMoveStarted(int reason) {
    if (reason == OnCameraMoveStartedListener.REASON_GESTURE) {
        Toast.makeText(this, "The user gestured on the map.",
                       Toast.LENGTH_SHORT).show();
    } else if (reason == OnCameraMoveStartedListener
                            .REASON_API_ANIMATION) {
        Toast.makeText(this, "The user tapped something on the map.",
                       Toast.LENGTH_SHORT).show();
    } else if (reason == OnCameraMoveStartedListener
                            .REASON_DEVELOPER_ANIMATION) {
        Toast.makeText(this, "The app moved the camera.",
                       Toast.LENGTH_SHORT).show();
    }
}
Giorgio
  • 1,973
  • 4
  • 36
  • 51
Flaviu Nes
  • 191
  • 1
  • 2
  • 4