Как сохранить пин-код и карту в центре над движущимся наложением в MKMapView

Как я могу держать булавку по центру на карте, пока я перемещаю (с помощью Панорамирования) другой вид по вертикали над картой так, чтобы булавка оставалась над оверлеем (не фактическим оверлеем MapKit).

Смотрите прикрепленные скриншоты для первого и конечного состояний.

У меня есть CGRect пространства между оверлеем и верхней частью экрана, когда пользователь перемещается вверх / вниз. Однако то, как я использую это, чтобы переместить карту и закрепить ее, одновременно увеличивая масштаб карты, когда пользователь перемещается вверх... и снова уменьшая масштаб, когда пользователь перемещается вниз, до сих пор ускользало от меня.

Я пробовал разные подходы, от попытки отрегулировать видимый прямоугольник до настройки рамки вида карты. Ответ может заключаться в некотором обмане MKMapRect / Region.

Начальное состояние

Конечное состояние с наложением панорамирования вверх

(Значок руки от Freepik CC BY 3.0)

2 ответа

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

Я обновил код, чтобы он работал гладко.

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

Чтобы этот код работал, вы должны изменить настройку keithbhunter так, чтобы нижнее ограничение mapView было полностью прикреплено к основанию суперпредставления (а не к slideView (чтобы размер mapView всегда был таким же, как у суперпредставления). В остальном установка такая же.

введите описание изображения здесь

Также можно настроить величину увеличения с помощью переменной maxMetersDistance

Здесь я всегда на Эйфелевой башне

введите описание изображения здесьвведите описание изображения здесь

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

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

}

Чтобы настроить виды, поместите вид карты и UIView на ваш взгляд контроллер. Используйте autolayout, чтобы прикрепить левую, верхнюю и правую стороны вида карты к суперпредставлению. Затем прикрепите нижнюю часть вида карты к верхней части UIView, Затем прикрепите левую, нижнюю и правую стороны UIView к суперпредставлению. Наконец, установите ограничение высоты на UIView к тому, что вы хотите инициализировать. Это значение высоты будет изменено, когда пользователь перетаскивает вид. Это позволяет UIView расти, как нам угодно, и одновременно успокаивать автопокрытие.

Добавить @IBOutlet к вашему контроллеру для просмотра карты, UIView и UIViewограничение по высоте, как в коде выше. regionDistance свойство это то, что делает магию масштабирования здесь. Это экспоненциальное уравнение (которое я сделал случайным образом), которое будет вычислять регион для большего или меньшего размера на основе высоты вида карты. reloadMap() использует это, чтобы обновить масштаб карты. Связать все это вместе UIPanGestureRecognizer на UIViewчто и контролирует UIViewвысота, вызывая масштабирование на карте.

Ловушка: это заставляет карту обновлять регион быстрее, чем она может загружать регион, что делает ее очень нервной. Наверное, есть способы обойти это. Будьте креативны.

Координата, которую я использовал в этом примере, является штаб-квартирой Apple.

Штаб-квартира Apple

Другие вопросы по тегам