I’m trying to setup an onDrag Listener for a google map fragment, but can’t get the drag event to fire. Since the map doesn\'t support drag events directly, I\'m trying to i
1) Create wrapper class:
public class MapWrapperLayout extends FrameLayout {
public interface OnDragListener {
public void onDrag(MotionEvent motionEvent);
}
private OnDragListener mOnDragListener;
public MapWrapperLayout(Context context) {
super(context);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if (mOnDragListener != null) {
mOnDragListener.onDrag(ev);
}
return super.dispatchTouchEvent(ev);
}
public void setOnDragListener(OnDragListener mOnDragListener) {
this.mOnDragListener = mOnDragListener;
}
}
2) Create subclass of MapFragment class:
public class CustomMapFragment extends SupportMapFragment {
private View mOriginalView;
private MapWrapperLayout mMapWrapperLayout;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
mOriginalView = super.onCreateView(inflater, container, savedInstanceState);
mMapWrapperLayout = new MapWrapperLayout(getActivity());
mMapWrapperLayout.addView(mOriginalView);
return mMapWrapperLayout;
}
@Override
public View getView() {
return mOriginalView;
}
public void setOnDragListener(MapWrapperLayout.OnDragListener onDragListener) {
mMapWrapperLayout.setOnDragListener(onDragListener);
}
3.1) Finally, in your activity:
// Google map init block
CustomMapFragment customMapFragment = ((CustomMapFragment) getSupportFragmentManager().findFragmentById(R.id.map));
customMapFragment.setOnDragListener(new MapWrapperLayout.OnDragListener() {
@Override
public void onDrag(MotionEvent motionEvent) {
Log.d("ON_DRAG", String.format("ME: %s", motionEvent));
// Handle motion event:
}
});
GoogleMap map = customMapFragment.getMap();
3.2) ... and in your layout:
<fragment android:id="@+id/map"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:name="your.package.CustomMapFragment"/>
To get drag event listener a fragment containing googleMap, one can use below method of google. We can get the target position of map.
googleMap.setOnCameraIdleListener(new GoogleMap.OnCameraIdleListener() {
@Override
public void onCameraIdle() {
Log.e(TAG,"==camera idle=="+ googleMap.getCameraPosition().target);
}
});
googleMap.setOnCameraMoveStartedListener(new GoogleMap.OnCameraMoveStartedListener() {
@Override
public void onCameraMoveStarted(int reason) {
if (reason ==REASON_GESTURE) {
isMaptouched=true;
Toast.makeText(getActivity(), "The user gestured on the map.",
Toast.LENGTH_SHORT).show();
} else if (reason ==REASON_API_ANIMATION) {
Toast.makeText(getActivity(), "The user tapped something on the map.",
Toast.LENGTH_SHORT).show();
} else if (reason ==REASON_DEVELOPER_ANIMATION) {
Toast.makeText(getActivity(), "The app moved the camera.",
Toast.LENGTH_SHORT).show();
}
}
});
I did something like similar using a BehaviorSubject to tell if the map was dirty (moved by user)
storeMap.setOnCameraMoveStartedListener(new GoogleMap.OnCameraMoveStartedListener() {
@Override
public void onCameraMoveStarted(int reason) {
if (reason == REASON_GESTURE) {
mapIsDirty.onNext(true);
}
}
});
storeMap.setOnCameraIdleListener(new OnCameraIdleListener() {
@Override
public void onCameraIdle() {
if(mapIsDirty.getValue()) {
// Do happy things
mapIsDirty.onNext(false);
}
}
});
I solved it using the onCameraMoveCancelledListener:
mMap.setOnMapClickListener(new GoogleMap.OnMapClickListener() {
@Override
public void onMapClick(LatLng latLng) {
stopCamera=true;
}
});
mMap.setOnCameraMoveCanceledListener(new GoogleMap.OnCameraMoveCanceledListener() {
@Override
public void onCameraMoveCanceled() {
stopCamera = true;
}
});