In my current android application, User will have the option to select their address by placing the marker on the map. The marker always stays in the center of the map. When the user is trying to zoom into the location by using gestures (pinching the map), the marker is changing its position, while using the zoom buttons everything is fine. How do I avoid moving the marker in the gesture case by moving the marker when using a single finger and only applying the gestures when using multiple fingers.
Create TouchableWrapper
and use it in MapFragment
public class TouchableWrapper extends FrameLayout {
private GoogleMap mGoogleMap = null;
public TouchableWrapper(Context context) {
super(context);
}
public void setGoogleMap(GoogleMap googleMap) {
mGoogleMap = googleMap;
}
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
mScaleDetector.onTouchEvent(event);
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
mGoogleMap.getUiSettings().setScrollGesturesEnabled(true);
long thisTime = System.currentTimeMillis();
if (thisTime - mLastTouchTime < ViewConfiguration.getDoubleTapTimeout()) {
if (mGoogleMap != null) {
LatLng zoomCenter = mGoogleMap.getProjection().fromScreenLocation(new Point((int) event.getX(), (int) event.getY()));
float currentZoom = mGoogleMap.getCameraPosition().zoom;
int mapViewHeight = getHeight();
int mapViewWidth = getWidth();
Projection projection = mGoogleMap.getProjection();
geographicalPosition = projection.fromScreenLocation(new Point(mapViewWidth / 2, mapViewHeight / 2));
mGoogleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(geographicalPosition.latitude, geographicalPosition.longitude), currentZoom + 1));
}
mLastTouchTime = -1;
} else {
mLastTouchTime = thisTime;
mGoogleMap.getUiSettings().setZoomGesturesEnabled(false);
}
break;
case MotionEvent.ACTION_POINTER_DOWN:
mGoogleMap.getUiSettings().setZoomGesturesEnabled(false);
mGoogleMap.getUiSettings().setScrollGesturesEnabled(false);
break;
case MotionEvent.ACTION_POINTER_UP:
mGoogleMap.getUiSettings().setScrollGesturesEnabled(true);
break;
case MotionEvent.ACTION_UP:
mGoogleMap.getUiSettings().setScrollGesturesEnabled(true);
break;
}
return super.dispatchTouchEvent(event);
}
ScaleGestureDetector mScaleDetector = new ScaleGestureDetector(getContext(),
new ScaleGestureDetector.SimpleOnScaleGestureListener() {
private float scaleFactor = 1f;
@Override
public boolean onScale(ScaleGestureDetector detector) {
// store scale factor for detect zoom "direction" on end
scaleFactor = detector.getScaleFactor();
float currentZoom = mGoogleMap.getCameraPosition().zoom;
int mapViewHeight = getHeight();
int mapViewWidth = getWidth();
if (scaleFactor > 1) {
// zoom in detected
geographicalPosition = mGoogleMap.getProjection().fromScreenLocation(new Point(mapViewWidth / 2, mapViewHeight / 2));
mGoogleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(geographicalPosition, currentZoom + 0.05f));
} else if (scaleFactor < 1) {
// zoom out detected
geographicalPosition = mGoogleMap.getProjection().fromScreenLocation(new Point(mapViewWidth / 2, mapViewHeight / 2));
mGoogleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(geographicalPosition, currentZoom - 0.05f));
}
return true;
}
@Override
public void onScaleEnd(ScaleGestureDetector detector) {
super.onScaleEnd(detector);
}
});
}
MapFragment
for that should be customized like:
public class MultiTouchMapFragment 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());
mTouchView.addView(mOriginalContentView);
return mTouchView;
}
@Override
public View getView() {
return mOriginalContentView;
}
}
in MainActivity
:
public class MainActivity extends AppCompatActivity implements OnMapReadyCallback {
private GoogleMap mGoogleMap;
private MultiTouchMapFragment mMapFragment;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mMapFragment = (MultiTouchMapFragment) getFragmentManager()
.findFragmentById(R.id.map_fragment);
mMapFragment.getMapAsync(this);
}
@Override
public void onMapReady(GoogleMap googleMap) {
mGoogleMap = googleMap;
mMapFragment.mTouchView.setGoogleMap(mGoogleMap);
}
}