Keep map centered regardless of where you pinch zoom on android

前端 未结 5 773
谎友^
谎友^ 2020-12-01 11:10

I\'m looking to do something similar to the way Uber handles pinch zoom events. No matter where you pinch on the screen, it keeps the map centered and zooms in on the center

5条回答
  •  再見小時候
    2020-12-01 12:08

    I had the same requirement as well. I had to understand how the events are handled in android to solve this problem, because we have to intercept the touch event for zoom and pass the scroll event to the map. To achieve this, we need a custom View over Google map View. Our custom view intercepts touch events, and decides whether to handle the follow-up events by not giving a chance for underlying map to handle or just leave the underlying map to handle all by itself.

    Now code time - We need two things here - a custom fragment, a custom view.

    1. Custom fragment

      public class CustomMapFragment extends SupportMapFragment implements OnMapReadyCallback {
      
      public View mapView = null;
      
      public WrapperView wrapperView = null;
      
      @Override
      public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {
          mapView = super.onCreateView(inflater, parent, savedInstanceState);
          wrapperView = new WrapperView(getActivity());
          wrapperView.addView(mapView);
          SupportMapFragment mapFragment = (SupportMapFragment) getActivity().getSupportFragmentManager().findFragmentById(R.id.map);
          mapFragment.getMapAsync(this);
          return wrapperView;
      }
      
      @Override
      public View getView() {
          return mapView;
      }
      
      @Override
      public void onMapReady(GoogleMap googleMap) {
          wrapperView.setGoogleMap(googleMap);
      }
      
    2. Custom View

      public class WrapperView extends FrameLayout {
      
      private GoogleMap googleMap;
      
      Activity activity = null;
      
      ScaleGestureDetector scaleGestureDetector;
      
      public WrapperView(Activity activity) {
          super(activity);
          this.activity=activity;
          scaleGestureDetector = new ScaleGestureDetector(activity ,new MyOnScaleGestureListener());
      }
      
      public void setGoogleMap(GoogleMap map){
          googleMap = map;
      }
      
      private boolean isZoomInProgress(MotionEvent event){
          if(event.getPointerCount()>1){
              return true;
          }
          return false;
      }
      
      @Override
      public boolean onInterceptTouchEvent(MotionEvent event){
          return isZoomInProgress(event);
      }
      
      @Override
      public boolean onTouchEvent(MotionEvent event){
          return scaleGestureDetector.onTouchEvent(event);
      }
      
      public class MyOnScaleGestureListener extends
              ScaleGestureDetector.SimpleOnScaleGestureListener {
      
          @Override
          public boolean onScale(ScaleGestureDetector detector) {
              float previousSpan = detector.getPreviousSpan();
              float currentSpan = detector.getCurrentSpan();
              float targetSpan;
              if(previousSpan>currentSpan){
                  targetSpan = previousSpan-currentSpan;
              }else{
                  targetSpan = currentSpan-previousSpan;
              }
              float scaleFactor = detector.getScaleFactor();
              if (scaleFactor > 1) {
                  if(googleMap.getCameraPosition().zoom!=googleMap.getMaxZoomLevel()) {
                      for(int j=0;j<(targetSpan*2);j++){
                          googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(googleMap.getCameraPosition().target, googleMap.getCameraPosition().zoom + 0.002f));
                      }
                  }
              } else {
                  if (googleMap.getCameraPosition().zoom != googleMap.getMinZoomLevel()) {
                      for(int j=0;j<(targetSpan*2);j++){
                          googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(googleMap.getCameraPosition().target, googleMap.getCameraPosition().zoom - 0.002f));
                      }
                  }
              }
              return true;
          }
      
          @Override
          public boolean onScaleBegin(ScaleGestureDetector detector) {
              return true;
          }
      
          @Override
          public void onScaleEnd(ScaleGestureDetector detector) {}
      }
      

    Use the new custom fragment in your view like below -

     
    

提交回复
热议问题