如何获得可拖动的MKAnnotationView而没有任何延迟

如何获得可拖动的MKAnnotationView而没有任何延迟

本文介绍了如何获得可拖动的MKAnnotationView而没有任何延迟?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下代码有效,并为我提供了可拖动的批注视图.但是,我注意到注解视图从一开始就不是可拖动的,而是仅在手指在注解视图上停留了一会儿之后才可拖动.直接进入拖动动作时,拖动不会影响注释视图,而是会平移地图.当然,它感觉不像拖放.无论是在设备上还是在模拟器中.

The below code works and gives me a draggable annotation view. However, I've noticed that the annotation view is not draggable from the very beginning on, but rather only after the finger has rested for a short moment on the annotation view. When directly going into a drag movement the dragging doesn't affect the annotation view but instead pans the map. It certainly doesn't feel like drag'n'drop. Both on the device and in the simulator.

ViewController(MapView的代表)

override func viewDidLoad() {
    /// ...
    let gestureRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(addPin))
    mapView.addGestureRecognizer(gestureRecognizer)
}

func addPin(gestureRecognizer: UIGestureRecognizer) {
    if gestureRecognizer.state != UIGestureRecognizerState.Began {
        return
    }
    for annotation in mapView.annotations {
        mapView.removeAnnotation(annotation)
    }
    let touchLocationInView = gestureRecognizer.locationInView(mapView)
    let coordinate = mapView.convertPoint(touchLocationInView, toCoordinateFromView: mapView)
    let annotation = DragAnnotation(coordinate: coordinate, title: "draggable", subtitle: "")
    mapView.addAnnotation(annotation)
}

func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {
    if annotation.isKindOfClass(DragAnnotation) {
        let reuseIdentifier = "DragAnnotationIdentifier"
        var annotationView: MKAnnotationView!
        if let dequeued = mapView.dequeueReusableAnnotationViewWithIdentifier(reuseIdentifier) {
            annotationView = dequeued
        } else {
            annotationView = MKAnnotationView(annotation: annotation, reuseIdentifier: reuseIdentifier)
        }
        annotationView.annotation = annotation
        annotationView.image = UIImage(named: "bluedisk2")
        annotationView.canShowCallout = false
        annotationView.draggable = true
        return annotationView
    }
    return nil
}

func mapView(mapView: MKMapView, annotationView view: MKAnnotationView, didChangeDragState newState: MKAnnotationViewDragState, fromOldState oldState: MKAnnotationViewDragState) {
    switch (newState) {
    case .Starting:
        view.dragState = .Dragging
    case .Ending, .Canceling:
        view.dragState = .None
    default: break
    }
}

DragAnnotation

import UIKit
import MapKit

class DragAnnotation : NSObject, MKAnnotation {
    var coordinate: CLLocationCoordinate2D {
        didSet {
            print(coordinate)
        }
    }
    var title: String?
    var subtitle: String?

    init(coordinate: CLLocationCoordinate2D, title: String, subtitle: String) {
        self.coordinate = coordinate
        self.title = title
        self.subtitle = subtitle
    }
}

推荐答案

我认为您无法更改可拖动的延迟,但是可以禁用它并添加没有延迟(或更短延迟)的自己的拖动手势:

I don't think you can change the draggable delay, but you could disable it and add your own drag gesture that has no delay (or a shorter delay):

func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {
    if annotation is MKUserLocation { return nil }

    var view = mapView.dequeueReusableAnnotationViewWithIdentifier("Foo")
    if view == nil {
        view = MKPinAnnotationView(annotation: annotation, reuseIdentifier: "Foo")
        view?.draggable = false

        let drag = UILongPressGestureRecognizer(target: self, action: #selector(handleDrag(_:)))
        drag.minimumPressDuration = 0 // set this to whatever you want
        drag.allowableMovement = .max
        view?.addGestureRecognizer(drag)
    } else {
        view?.annotation = annotation
    }

    return view
}

private var startLocation = CGPointZero

func handleDrag(gesture: UILongPressGestureRecognizer) {
    let location = gesture.locationInView(mapView)

    if gesture.state == .Began {
        startLocation = location
    } else if gesture.state == .Changed {
        gesture.view?.transform = CGAffineTransformMakeTranslation(location.x - startLocation.x, location.y - startLocation.y)
    } else if gesture.state == .Ended || gesture.state == .Cancelled {
        let annotationView = gesture.view as! MKAnnotationView
        let annotation = annotationView.annotation as! DragAnnotation

        let translate = CGPoint(x: location.x - startLocation.x, y: location.y - startLocation.y)
        let originalLocation = mapView.convertCoordinate(annotation.coordinate, toPointToView: mapView)
        let updatedLocation = CGPoint(x: originalLocation.x + translate.x, y: originalLocation.y + translate.y)

        annotationView.transform = CGAffineTransformIdentity
        annotation.coordinate = mapView.convertPoint(updatedLocation, toCoordinateFromView: mapView)
    }
}

如果要更改注释的coordinate,则需要在自定义类coordinate声明中添加dynamic关键字,以便发出适当的KVO通知. /p>

By the way, if you're going to change the coordinate of an annotation, you will want to add dynamic keyword to your custom class coordinate declaration so that the appropriate KVO notifications will be issued.

class DragAnnotation: NSObject, MKAnnotation {
    dynamic var coordinate: CLLocationCoordinate2D
    var title: String?
    var subtitle: String?

    init(coordinate: CLLocationCoordinate2D, title: String? = nil, subtitle: String? = nil) {
        self.coordinate = coordinate
        self.title = title
        self.subtitle = subtitle
        super.init()
    }
}

注意,在此示例中,我将延迟设置为零.这意味着,如果您点击注释(显示标注"的典型UI),则可能会阻止其正常工作.它将视为一个很短的阻力.这就是为什么标准UI在拖动之前需要长按延迟的原因.

Note, in this example, I set the delay to zero. That means that if you tap on the annotation (the typical UI for "show the callout"), this may prevent that from working correctly. It will treat this as a very short drag. This is why the standard UI requires a delay in the long press before dragging.

因此,由于这个原因,我个人会犹豫重写上面显示的此行为,因为它将不同于最终用户熟悉的标准地图行为.如果您的地图在行为上与用户设备上的任何其他地图不同,则可能是感到沮丧的原因.

So, for this reason, I personally would hesitate to override this behavior shown above because it will be different then standard map behavior that the end user is familiar with. If your map behaves differently than any other maps on the user's device, this could be a source of frustration.

这篇关于如何获得可拖动的MKAnnotationView而没有任何延迟?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-15 16:07