Подтвердить что ты не робот

Запретить прокрутку в MKMapView, также при масштабировании

scrollEnabled кажется прерывистым, когда пользователь начинает зажимать в MKMapView.

Вы все еще не можете прокручивать одним пальцем, но если вы прокручиваете двумя пальцами во время увеличения и уменьшения масштаба, вы можете переместить карту.

Я пробовал:

  • Подклассификация MKMapKit, чтобы отключить просмотр прокрутки внутри него.
  • Реализация - mapView:regionWillChangeAnimated: для обеспечения центра.
  • Отключение scrollEnabled.

но не повезло.

Может ли кто-нибудь сказать мне верный способ ТОЛЬКО масштабировать MKMapView, поэтому центральная точка всегда находится посередине?

4b9b3361

Ответ 1

Вы можете сами пытаться обрабатывать жесты пинча, используя UIPinchGestureRecognizer:

Сначала установите scrollEnabled и zoomEnabled в NO и создайте распознаватель жестов:

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

В обработчике распознавателя отрегулируйте MKCoordinateSpan в соответствии с масштабом масштабирования:

- (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];
}

Это может работать не так, как реализация Apple, но она должна решить вашу проблему.

Ответ 2

Попробуйте реализовать –mapView:regionWillChangeAnimated: или –mapView:regionDidChangeAnimated: в своем делете делегата карты, чтобы карта всегда была в центре вашего предпочтительного местоположения.

Ответ 3

Я читал об этом раньше, хотя я никогда не пробовал это. Взгляните на эту статью о MKMapView с границами. Он использует два метода делегирования, чтобы проверить, было ли прокручено изображение пользователем.

http://blog.jamgraham.com/blog/2012/04/29/adding-boundaries-to-mkmapview

В статье описывается подход, похожий на то, что вы пробовали, поэтому, извините, если вы уже наткнулись на него.

Ответ 4

Мне не повезло с этими ответами. Выполнение моего собственного щепотка просто слишком сильно противоречило. Я сталкивался с ситуациями, когда нормальный зум увеличивался бы дальше, чем я мог бы сделать с моим собственным щепоткой.

Изначально я старался как оригинальный плакат сделать что-то вроде:

- (void) mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated {
    MKCoordinateRegion region = mapView.region;
    //...
    // adjust the region.center 
    //...
    mapView.region = region;
}

Я обнаружил, что это не повлияло. Я также обнаружил через NSLog, что этот метод срабатывает, даже когда я программно устанавливаю region или centerCoordinate. Это привело к вопросу: "Разве это не было бы, если бы он работал бесконечно?"

Итак, сейчас я выдвигаю гипотезу и выдвигаю гипотезу, что, когда пользовательский масштаб/прокрутка/поворот происходит, MapView каким-то образом подавляет или игнорирует изменения в регионе. Что-то в арбитраже делает программную корректировку импотентом.

Если это проблема, то, возможно, ключ должен получить настройку области вне уведомления regionDidChanged:. И так как любая настройка приведет к еще одному уведомлению, важно, чтобы она могла определить, когда больше не настраиваться. Это привело меня к следующей реализации (где subject обеспечивает координату центра, которую я хочу поселиться посередине):

- (void) recenterMap {
    double latDiff = self.subject.coordinate.latitude self.mapView.centerCoordinate.latitude;
    double lonDiff = self.subject.coordinate.longitude - self.mapView.centerCoordinate.longitude;
    BOOL latIsDiff = ABS(latDiff) > 0.00001;
    BOOL lonIsDiff = ABS(lonDiff) > 0.00001;
    if (self.subject.isLocated && (lonIsDiff || latIsDiff)) {
        [self.mapView setCenterCoordinate: self.subject.coordinate animated: YES];
    }
}

- (void) mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated {
    if (self.isShowingMap) {
        if (self.isInEdit) {
            self.setLocationButton.hidden = NO;
            self.mapEditPrompt.hidden = YES;
        }
        else {
            if (self.subject.isLocated) { // dispatch outside so it will happen after the map view user events are done
                 dispatch_after(DISPATCH_TIME_NOW, dispatch_get_main_queue(), ^{
                    [self recenterMap];
                });
            }
        }
    }
}

Задержка, при которой он может сместиться, может изменяться, но на самом деле это работает очень хорошо. И позволяет взаимодействию с картами оставаться Apple-esque, когда это происходит.

Ответ 5

Я пробовал это, и он работает.

Сначала создайте свойство:

var originalCenter: CLLocationCoordinate2D?

Затем в regionWillChangeAnimated проверьте, вызвано ли это событие UIPinchGestureRecognizer:

func mapView(mapView: MKMapView, regionWillChangeAnimated animated: Bool) {
    let firstView = mapView.subviews.first
    if let recognizer = firstView?.gestureRecognizers?.filter({ $0.state == .Began || $0.state == .Ended }).first as? UIPinchGestureRecognizer {
        if recognizer.scale != 1.0 {
            originalCenter = mapView.region.center
        }
    }
}

Затем в областиDidChangeAnimated вернитесь к исходной области, если жест щепотки изменил область:

func mapView(mapView: MKMapView, regionDidChangeAnimated animated: Bool) {
    if let center = originalCenter {
        mapView.setRegion(MKCoordinateRegion(center: center, span: mapView.region.span), animated: true)
        originalCenter = nil
        return
    }
// your other code 
}

Ответ 6

Swift 3.0 версия @Paras Joshi отвечает fooobar.com/info/247517/...

с небольшим исправлением анимации.

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)

    }
}