2015-05-17 10 views
6

Jak zachować szpilkę wyśrodkowaną na mapie, podczas gdy poruszam (za pomocą Pan Gesture) innym widokiem pionowo nad mapą tak, aby pin pozostał powyżej nakładki (nie rzeczywistą nakładkę MapKit).Jak zachować pinezkę i mapę wyśrodkowaną powyżej ruchomej nakładki w MKMapView

Zobacz załączone zrzuty ekranu dla pierwszego i ostatniego stanu.

Mam CGRect przestrzeni między nakładką a górną częścią ekranu, gdy patelnia użytkownika jest w górę/w dół. Jednak, jak tego użyć, aby przesunąć mapę i przypiąć podczas powiększania mapy, gdy użytkownik patrzy w górę ... i zmniejszyć ponownie, gdy użytkownik patrzy w dół, umyka mi do tej pory.

Próbowałem różnych podejść, od próby dostosowania widocznego prostokąta do dopasowania ramki widoku mapy. Odpowiedź może leżeć w jakimś MKMapRect/oszustwa Region ..

Initial state

Final state with overlay panned upward

(ikona ręcznie przez Freepik CC BY 3.0)

+0

próbowałeś 'setCenterCoordinate' podejście? –

+0

Czy mapa ma być powiększana i zmniejszana podczas przesuwania nakładki? – keithbhunter

+0

@keithbhunter Tak, do wewnątrz, gdy patrzysz w górę i na zewnątrz, gdy przesuwasz się w dół .. – Aodh

Odpowiedz

4
class ViewController: UIViewController { 

    @IBOutlet weak var mapView: MKMapView! 
    @IBOutlet weak var slidingView: UIView! 
    @IBOutlet weak var slidingViewHeight: NSLayoutConstraint! 


    override func viewDidLoad() { 
     super.viewDidLoad() 
     self.reloadMap() 
     let pan = UIPanGestureRecognizer(target: self, action: "viewDidPan:") 
     self.slidingView.addGestureRecognizer(pan) 
    } 

    func reloadMap() { 
     let coordinate = CLLocationCoordinate2D(latitude: 37.332363, longitude: -122.030805) 
     let height = Double(self.mapView.frame.size.height) 
     let regionDistance = 0.3 * height * height // random multiplier and exponential equation for scaling 
     let region = MKCoordinateRegionMakeWithDistance(coordinate, regionDistance, regionDistance) 
     self.mapView.setRegion(region, animated: false) 
    } 

    func viewDidPan(panGesture: UIPanGestureRecognizer) { 
     let location = panGesture.locationInView(self.view) 
     self.slidingViewHeight.constant = self.view.frame.size.height - location.y 
     self.reloadMap() 
    } 

} 

Aby skonfigurować widoki, umieść mapę widoku i UIView w kontrolerze widoku. Użyj autolayout, aby przypiąć widok mapy z lewej, prawej i prawej strony do podglądu. Następnie przypnij dolną część widoku mapy do górnej części UIView. Następnie przypnij lewą, dolną i prawą stronę modelu UIView do podglądu. Na koniec ustaw ograniczenie wysokości na UIView do tego, co chcesz, aby zainicjować. Ta wartość wysokości zostanie zmieniona, gdy użytkownik przeciągnie widok. To pozwala, aby UIView rosło tak, jak nam się podobało i jednocześnie uśmierzało autolayout.

Dodaj @IBOutlet do kontrolera widoku dla widoku mapy, ograniczenia wysokości na UIView i UIView, jak w powyższym kodzie. Właściwość regionDistance jest tym, co robi tutaj powiększająca magia. Jest to równanie wykładnicze (które tworzyłem losowo), które obliczy region na większy lub mniejszy na podstawie wysokości widoku mapy. reloadMap() używa tego do aktualizacji powiększenia mapy. Łączenie go w całość to UIPanGestureRecognizer na UIView, która kontroluje wysokość, powodując działanie powiększania na mapie.

Pułapka: Zmusza to mapę do aktualizacji regionu szybciej niż może załadować region, co sprawia, że ​​wygląda bardzo skocznie. Prawdopodobnie istnieją sposoby obejścia tego. Bądź kreatywny.

Współrzędną, której użyłem w tym przykładzie, jest siedziba firmy Apple.

Apple's HQ

5

Właściwie kod keithbhunter jest powolny, ponieważ oprócz aktualizowania region szybciej niż może go załadować, mapa zmienia się także wysokość, która powoduje dodatkowe obciążenie!

Zaktualizowałem kod tak, aby działał płynnie.

Tym kodem, co robię, jest utrzymanie mapy w tym samym rozmiarze, ale zamiast tego przesuwaj punkt środkowy, aby zrekompensować wysokość przesuwanego widoku.

Aby ten kod zadziałał, musisz zmodyfikować konfigurację keithbhuntera tak, aby dolne ograniczenie mapView zostało całkowicie przypięte do dołu widoku (a nie do przesuwnego widoku (aby mapView zawsze miał taki sam rozmiar jak super widok) . dla reszty konfiguracja jest taka sama.

enter image description here

również możliwe jest dostosowanie ilości zoom ze zmienną maxMetersDistance

ja tu jestem, zawsze skupiając się na wieżą Eifla

enter image description here enter image description here

import UIKit 
import MapKit 

class ViewController: UIViewController { 

    @IBOutlet weak var mapView: MKMapView! 
    @IBOutlet weak var slidingView: UIView! 
    @IBOutlet weak var slidingViewHeight: NSLayoutConstraint! 
    var maxMetersDistance:CGFloat = 10000.0; // customize this to set how far the map zooms out of the interest area 

    override func viewDidLoad() { 
     super.viewDidLoad() 
     let pan = UIPanGestureRecognizer(target: self, action: "viewDidPan:") 
     self.slidingView.addGestureRecognizer(pan) 
     firstTimeCenter() 
    } 

    func firstTimeCenter(){ 
     var coordinate = CLLocationCoordinate2D(latitude: 48.8582, longitude: 2.2945) 
     let region = MKCoordinateRegionMakeWithDistance(coordinate, Double(maxMetersDistance), Double(maxMetersDistance)) 
     self.mapView.setRegion(region, animated: true) 
    } 

    func reloadMap() { 
     let height = CGFloat(self.slidingViewHeight.constant) 
     var regionDistance = (maxMetersDistance/self.view.frame.height) * height 
     regionDistance = maxMetersDistance - regionDistance 
     var coordinate = CLLocationCoordinate2D(latitude: 48.8582, longitude: 2.2945) 
     var mapRect = mapView.visibleMapRect; 
     var metersPerMapPoint = MKMetersPerMapPointAtLatitude(coordinate.latitude); 
     var metersPerPixel = CGFloat(metersPerMapPoint) * CGFloat(mapRect.size.width)/CGFloat(mapView.bounds.size.width); 
     var totalMeters = Double(metersPerPixel) * Double(height/2) 

     coordinate = self.translateCoord(coordinate, MetersLat: -totalMeters, MetersLong: 0.0) 

     let region = MKCoordinateRegionMakeWithDistance(coordinate, Double(regionDistance), Double(regionDistance)) 
     self.mapView.setRegion(region, animated: false) 
    } 

    func viewDidPan(panGesture: UIPanGestureRecognizer) { 
     let location = panGesture.locationInView(self.view) 
     self.slidingViewHeight.constant = self.view.frame.size.height - location.y 
     self.reloadMap() 
    } 

    func translateCoord(coord:CLLocationCoordinate2D, MetersLat:Double, MetersLong:Double)->CLLocationCoordinate2D{ 
     var tempCoord = CLLocationCoordinate2D() 
     var tempRegion = MKCoordinateRegionMakeWithDistance(coord, MetersLat, MetersLong); 
     var tempSpan = tempRegion.span; 
     tempCoord.latitude = coord.latitude + tempSpan.latitudeDelta; 
     tempCoord.longitude = coord.longitude + tempSpan.longitudeDelta; 
     return tempCoord; 
    } 

} 
+0

Dzięki Juan & Keith! W rozwiązaniu Juana jest trochę zawziętości, które muszę wymyślić, ale jest to bardzo zbliżone do tego, czego szukałem :) – Aodh

Powiązane problemy