I want to intercept all click and touch on Google Maps fragment.
For my use case, I have a small map fragment in my activity. Once user click or touch or drag or pinch on the map fragment, it will launch an activity with a fullscreen map.
GoogleMap listeners
The easiest method is to utilize GoogleMap's listeners:
setOnMapClickListener
- the map is clicked (will not trigger if marker is clicked)setOnMarkerClickListener
- the marker is clickedsetOnCameraMoveStartedListener
- touch, drag or pinch event (scroll and zoom)
mapFragment.getMapAsync(new OnMapReadyCallback() { @Override public void onMapReady(final GoogleMap map) { map.setOnMapClickListener(new GoogleMap.OnMapClickListener() { @Override public void onMapClick(LatLng latLng) { Log.d(TAG, "onMapClick"); startMap(); } }); map.setOnCameraMoveStartedListener(new GoogleMap.OnCameraMoveStartedListener() { @Override public void onCameraMoveStarted(int reason) { if (reason == GoogleMap.OnCameraMoveStartedListener.REASON_GESTURE) { Log.d(TAG, "onCameraMoveStarted"); startMap(); } } }); map.setOnMarkerClickListener(new GoogleMap.OnMarkerClickListener() { @Override public boolean onMarkerClick(Marker marker) { Log.d(TAG, "onMarkerClick"); startMap(); return true; } }); }});
I want the map to remain static, where it cannot be scrolled or zoomed by the user. The above listeners doesn't prevent that.
I can use map.getUiSettings().setAllGesturesEnabled(false)
to disable gestures and make the map static. The problem is that only the click listener are triggered, where nothing happens if user touch, drag or pinch the map. I want to receive an event when user touch, drag or pinch the map.
// disable all gestures, OnCameraMoveStartedListener will not be triggeredmap.getUiSettings().setAllGesturesEnabled(false);
Extend SupportMapFragment with TouchableWrapper
To intercept all click and touch events and prevent the events from being replayed to Google Maps, we need extend SupportMapFragment
.
We add a FrameLayout
as an overlay on map view, overriding dispatchTouchEvent
and consume all MotionEvent.ACTION_DOWN
events.
public class StaticMapFragment extends SupportMapFragment { public View mapView; public TouchableWrapper touchView; private StaticMapFragment.OnTouchListener listener; public static StaticMapFragment newInstance() { return new StaticMapFragment(); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) { mapView = super.onCreateView(inflater, parent, savedInstanceState); // overlay a touch view on map view to intercept the event touchView = new TouchableWrapper(getActivity()); touchView.addView(mapView); return touchView; } @Override public View getView() { return mapView; } public void setOnTouchListener(StaticMapFragment.OnTouchListener listener) { this.listener = listener; } public interface OnTouchListener { void onTouch(); } public class TouchableWrapper extends FrameLayout { public TouchableWrapper(Context context) { super(context); } @Override public boolean dispatchTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: if (listener != null) { listener.onTouch(); } // consume event to prevent map from receiving the event return true; } return super.dispatchTouchEvent(event); } }}
Usage.
mapFragment.setOnTouchListener(new StaticMapFragment.OnTouchListener() { @Override public void onTouch() { Log.d(TAG, "onTouch"); startMap(); }});