在 google 地图中使用双指缩放以当前位置为地图中心进行放大和缩小
In google map using pinch to zoom in and zoom out with the current location as centre of the map
在我当前的 android 应用程序中,用户可以选择 select 他们的地址,方法是在地图上放置标记。标记始终位于地图的中心。当用户尝试使用手势(捏合地图)放大位置时,标记正在改变其位置,而使用缩放按钮一切正常。如何通过在使用单指时移动标记并在使用多指时仅应用手势来避免在手势情况下移动标记。
创建TouchableWrapper
并在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
应该定制为:
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;
}
}
在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);
}
}
在我当前的 android 应用程序中,用户可以选择 select 他们的地址,方法是在地图上放置标记。标记始终位于地图的中心。当用户尝试使用手势(捏合地图)放大位置时,标记正在改变其位置,而使用缩放按钮一切正常。如何通过在使用单指时移动标记并在使用多指时仅应用手势来避免在手势情况下移动标记。
创建TouchableWrapper
并在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
应该定制为:
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;
}
}
在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);
}
}