下面的代码有效,并为我提供了一个可拖动的注释视图。但是,我注意到注释视图从一开始就不能拖动,而只能在手指在注释视图上停留片刻之后才能拖动。当直接进入拖动运动时,拖动不会影响注释视图,而是平移地图。这当然不像拖放的感觉。无论是在设备上还是在模拟器中。
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
}
}
Run Code Online (Sandbox Code Playgroud)
拖动注释
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
}
}
Run Code Online (Sandbox Code Playgroud)
我不认为您可以更改可拖动延迟,但您可以禁用它并添加您自己的没有延迟(或更短延迟)的拖动手势:
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)
}
}
Run Code Online (Sandbox Code Playgroud)
顺便说一下,如果您要更改coordinate注释的 ,您需要dynamic在自定义类coordinate声明中添加关键字,以便发出适当的 KVO 通知。
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()
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,在此示例中,我将延迟设置为零。这意味着如果您点击注释(“显示标注”的典型 UI),这可能会阻止其正常工作。它将将此视为非常短的阻力。这就是为什么标准 UI 在拖动之前需要延迟长按。
因此,出于这个原因,我个人会犹豫是否覆盖上面显示的这种行为,因为它与最终用户熟悉的标准地图行为不同。如果您的地图的行为与用户设备上的任何其他地图不同,这可能会令人沮丧。
| 归档时间: |
|
| 查看次数: |
1070 次 |
| 最近记录: |