2012-08-06 14 views
21

Wydaje się, że scrollEnabled jest łamliwy, gdy użytkownik zacznie szczypanie w MKMapView.Zapobieganie przewijaniu w widoku MKMapView, także podczas przybliżania obrazu

Nadal nie można przewijać jednym palcem, ale jeśli przewijasz dwoma palcami podczas powiększania i pomniejszania, możesz przesunąć mapę.

Próbowałem:

  • instacji MKMapKit wyłączyć widok przewijania wewnątrz niego.
  • Implementacja - mapView:regionWillChangeAnimated: w celu wymuszenia środka.
  • Wyłączenie scrollEnabled.

ale bez powodzenia.

Czy ktoś może mi powiedzieć pewny sposób, aby TYLKO powiększyć widok MKMapView, więc punkt środkowy zawsze pozostaje w środku?

+2

Musiałem to zrobić wcześniej, ale zrobiłem to inaczej. Wyłączyłem interakcję z MKMapView i dodałem rozpoznawanie gestów szczypcami do widoku powyżej. Następnie przekonwertowałem gesty szczypania na odpowiadający im poziom powiększenia. Tak samo funkcjonalnie dostosowujesz swoje własne szczypanie do powiększenia. Widząc, że to nie odpowiada bezpośrednio na twoje pytanie, jeśli jest to opłacalna opcja, opublikuję w odpowiedziach kod. – random

Odpowiedz

29

Można próbować obsługiwać gesty szczyptę siebie za pomocą UIPinchGestureRecognizer:

Pierwszy set scrollEnabled i zoomEnabled do NO i stworzyć rozpoznawania gestów:

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

w obsługi funkcji Rozpoznawanie dostosować MKCoordinateSpan według Skala zoomu:

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

To może nie działać idealnie jak implementacja Apple, ale powinno rozwiązać twój problem.

+1

Nie sądzę, że to rozwiązanie jest tak wspaniałe. Czuje się bardzo przylega w porównaniu do domyślnego powiększenia zapewnianego przez jabłko. Np. Występuje opóźnienie między uszczypnięciem a aktualizacją ekranu. –

+0

to nie działa w ogóle. – Haitao

+0

zmiana animowana: TAK na animowaną: Nie w ostatniej linii [self.mapView setRegion: MKCoordinateRegionMake (originalRegion.center, span) animowane: TAK]; i jego działanie sprawnie. –

1

Spróbuj wprowadzić –mapView:regionWillChangeAnimated: lub –mapView:regionDidChangeAnimated: w delegacie widoku mapy, aby mapa była zawsze wyśrodkowana w preferowanej lokalizacji.

+0

Próbowałem ... Nie ma to żadnego efektu. –

1

Czytałem o tym wcześniej, chociaż nigdy tego nie próbowałem. Spójrz na ten artykuł na temat MKMapView z granicami. Używa dwóch metod delegowania, aby sprawdzić, czy widok został przewinięty przez użytkownika.

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

W artykule przedstawiono podejście, które jest podobne do tego, co próbowaliśmy, więc przepraszam jeśli już natknął się na niego.

1

Nie miałem dużo szczęścia z żadną z tych odpowiedzi. Robienie własnego uszczypnięcia zbytnio kolidowało. Występowałem w przypadkach, w których normalny zoom byłby większy niż w moim własnym szczypcie.

Początkowo próbowałem jak oryginalny plakat zrobić coś takiego:

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

co znalazłem było to, że nie miał wpływu. Odkryłem również, że ta metoda będzie uruchamiana, nawet jeśli ustawię programowo region lub centerCoordinate. Które doprowadziło do pytania: "Czy powyższe, gdyby to NIE DZIAŁAŁA, byłoby nieskończone?"

Więc jestem conjecturing i hipotez teraz, gdy zoom user/Scroll/obracać się dzieje, MapView jakoś hamuje lub ignoruje zmiany w tym regionie. Coś o arbitrażu renderuje programową regulację bezsilny.

Jeśli to problem, to może kluczem jest uzyskanie dostosowania regionu poza powiadomieniem regionDidChanged:. A ponieważ każda korekta wyzwala kolejne powiadomienie, ważne jest, aby był w stanie określić, kiedy nie należy już regulować. To doprowadziło mnie do następującej implementacji (gdzie subject podaje środkową współrzędną, którą chcę pozostawić w środku):

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

Opóźnienie w przesunięciu może się różnić, ale naprawdę działa całkiem dobrze. I pozwala interakcji mapy pozostać Apple-esque, podczas gdy to się dzieje.

1

Próbowałem tego i działa.

Najpierw utwórz właściwość:

var originalCenter: CLLocationCoordinate2D? 

Następnie w regionWillChangeAnimated sprawdzić, czy to zdarzenie jest spowodowane przez 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 
     } 
    } 
} 

Następnie w regionDidChangeAnimated, powrót do pierwotnego regionu czy gestem szczypta spowodowane region zmienia się:

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 
} 
1

Swift 3.0 wersja @Paras Joshi odpowiedź https://stackoverflow.com/a/11954355/3754976

z małą poprawką animacji.

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) 

    } 
} 
Powiązane problemy