2015-05-17 3 views
6

Wie kann ich einen Pin zentriert auf einer Karte halten, während ich (über Pan - Geste) eine andere Ansicht vertikal über die Karte bewege, so dass der Pin über dem Overlay bleibt (nicht ein tatsächliches MapKit-Overlay).Wie man Pin und Karte zentriert über bewegenden Overlay in einem MKMapView hält

Siehe beigefügte Screenshots für den ersten und letzten Status.

Ich habe den CGRect des Abstandes zwischen dem Overlay und dem oberen Bildschirmrand, wenn der Benutzer auf/ab geht. Wie ich das aber nutze, um die Karte zu bewegen und zu fixieren, während ich in die Karte zoome, während der Benutzer nach oben schwenkt ... und wieder herauszoomt, wenn der Benutzer nach unten schwenkt, ist mir bisher entgangen.

Ich habe verschiedene Ansätze ausprobiert, von dem Versuch, das sichtbare Rect anzupassen, um den Rahmen der Kartenansicht anzupassen. Die Antwort könnte in einigen MKMapRect/Region Tricks ..

Initial state

Final state with overlay panned upward

(Hand-Symbol von Freepik CC BY 3,0)

+0

haben Sie 'setCenterCoordinate' Ansatz versucht? –

+0

Soll die Karte beim Verschieben des Overlays vergrößert und verkleinert werden? – keithbhunter

+0

@keithbhunter Ja, nach innen, wie Sie nach oben und außen schwenken, wie Sie nach unten schwenken .. – Aodh

Antwort

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

} 

die Ansichten Zur Einstellung legen Sie eine Karte Ansicht und eine UIView in Ihrem View-Controller. Verwenden Sie das automatische Layout, um die linke, obere und rechte Seite der Kartenansicht an die Superansicht anzuheften. Dann stecken Sie den unteren Teil der Kartenansicht an die Spitze der UIView. Als nächstes stecken Sie die linke, untere und rechte Seite des UIView in die Superview. Setzen Sie zum Schluss eine Höhenzwangsbeschränkung für das UIView, auf das Sie es initialisieren möchten. Dieser Höhenwert wird geändert, wenn der Benutzer die Ansicht verschiebt. Dies ermöglicht es dem UIView, nach Belieben zu wachsen und das automatische Layout gleichzeitig zu beschwichtigen.

ein @IBOutlet zu Ihren View-Controller für die Kartenansicht hinzufügen, die UIView und die UIView ‚s Höhenbeschränkung, wie in dem obigen Code. Die regionDistance Eigenschaft ist, was hier die Zoom-Magie macht. Es ist eine exponentielle Gleichung (die ich zufällig erstellt habe), die basierend auf der Höhe der Kartenansicht die Region für größere oder kleinere berechnen wird. reloadMap() verwendet dies, um den Zoom der Karte zu aktualisieren. Alles zusammengebunden ist die UIPanGestureRecognizer auf der UIView, die die Höhe UIView steuert, verursacht die Zoomaktion auf der Karte.

Fallstricke: Dies zwingt die Karte, die Region schneller zu aktualisieren, als sie die Region laden kann, wodurch sie sehr unruhig aussieht. Es gibt wahrscheinlich Möglichkeiten, dies zu umgehen. Werde kreativ.

Die Koordinate, die ich im Beispiel verwendet habe, ist Apples Hauptquartier.

Apple's HQ

5

Eigentlich ist da langsam Code, keithbhunter ist neben der Region schneller zu aktualisieren, als sie es laden kann, wird die Karte auch Höhe zu verändern, die zusätzlichen Aufwand verursacht!

Ich habe den Code aktualisiert, so dass es reibungslos läuft.

Mit diesem Code halte ich die Kartenansicht auf der gleichen Größe, aber stattdessen verschiebe ich den Punkt der Mitte, um die Höhe der Schiebeansicht zu kompensieren.

Damit dieser Code funktioniert, müssen Sie die Einstellung von keithbhunter so ändern, dass die bottom-Constraint der mapView vollständig an die Unterseite der Superview angeheftet ist (und nicht an slidingView (so dass die mapView immer die gleiche Größe wie die Super View hat) das Setup. Für den Rest ist das gleiche.

enter image description here

auch ist es möglich, die Menge des Zooms mit der variablen maxMetersDistance

Hier bin ich, immer zentriert auf dem Eifelturm

anpassen

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

Dank Juan & Keith! Es gibt einige Sprunghaftigkeit in Juans Lösung, die ich herausfinden muss, aber das ist sehr nah an dem, was ich gesucht habe :) – Aodh

Verwandte Themen