在 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);
    }

}