Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Prevent scrolling in a MKMapView, also when zooming

The scrollEnabled seems to be breakable once the user starts pinching in a MKMapView.

You still can't scroll with one finger, but if you scroll with two fingers while zooming in and out, you can move the map.

I have tried :

  • Subclassing the MKMapKit to disable the scroll view inside it.
  • Implementing –mapView:regionWillChangeAnimated: to enforce the center.
  • Disabling scrollEnabled.

but with no luck.

Can anyone tell me a sure way to ONLY have zooming in a MKMapView, so the center point always stays in the middle ?

like image 400
Nils Munch Avatar asked Aug 06 '12 14:08

Nils Munch


3 Answers

You can try to handle the pinch gestures yourself using a UIPinchGestureRecognizer:

First set scrollEnabled and zoomEnabled to NO and create the gesture recognizer:

UIPinchGestureRecognizer* recognizer = [[UIPinchGestureRecognizer alloc] initWithTarget:self
                                                                                 action:@selector(handlePinch:)];
[self.mapView addGestureRecognizer:recognizer];

In the recognizer handler adjust the MKCoordinateSpan according to the zoom scale:

- (void)handlePinch:(UIPinchGestureRecognizer*)recognizer
{
    static MKCoordinateRegion originalRegion;
    if (recognizer.state == UIGestureRecognizerStateBegan) {
        originalRegion = self.mapView.region;
    }    

    double latdelta = originalRegion.span.latitudeDelta / recognizer.scale;
    double londelta = originalRegion.span.longitudeDelta / recognizer.scale;

    // TODO: set these constants to appropriate values to set max/min zoomscale
    latdelta = MAX(MIN(latdelta, 80), 0.02);
    londelta = MAX(MIN(londelta, 80), 0.02);
    MKCoordinateSpan span = MKCoordinateSpanMake(latdelta, londelta);

    [self.mapView setRegion:MKCoordinateRegionMake(originalRegion.center, span) animated:YES];
}

This may not work perfectly like Apple's implementation but it should solve your issue.

like image 54
Felix Avatar answered Nov 15 '22 15:11

Felix


Swift 3.0 version of @Paras Joshi answer https://stackoverflow.com/a/11954355/3754976

with small animation fix.

class MapViewZoomCenter: MKMapView {

    var originalRegion: MKCoordinateRegion!

    override func awakeFromNib() {
       self.configureView()
    }

    func configureView() {
        isZoomEnabled = false
        self.registerZoomGesture()
    }

    ///Register zoom gesture
    func registerZoomGesture() {
        let recognizer = UIPinchGestureRecognizer(target: self, action:#selector(MapViewZoomCenter.handleMapPinch(recognizer:)))
        self.addGestureRecognizer(recognizer)
    }

    ///Zoom in/out map
    func handleMapPinch(recognizer: UIPinchGestureRecognizer) {

        if (recognizer.state == .began) {
            self.originalRegion = self.region;
        }

        var latdelta: Double = originalRegion.span.latitudeDelta / Double(recognizer.scale)
        var londelta: Double = originalRegion.span.longitudeDelta / Double(recognizer.scale)

        //set these constants to appropriate values to set max/min zoomscale
        latdelta = max(min(latdelta, 80), 0.02);
        londelta = max(min(londelta, 80), 0.02);

        let span = MKCoordinateSpanMake(latdelta, londelta)

        self.setRegion(MKCoordinateRegionMake(originalRegion.center, span), animated: false)

    }
}
like image 31
Afzaal Ahmad Avatar answered Nov 15 '22 15:11

Afzaal Ahmad


Try implementing –mapView:regionWillChangeAnimated: or –mapView:regionDidChangeAnimated: in your map view's delegate so that the map is always centered on your preferred location.

like image 1
Caleb Avatar answered Nov 15 '22 14:11

Caleb