I have an array of coordinates and draw a polyline using these. At center of polyline I m showing an annotation using MKAnnotationView. This is dragable, I want it to be dragged only with adjesent to or over the polyline. Do not allow user to move and drag away from polyline?
How this could be done any ideas ?
I only found this delegate method
func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView, didChange newState: MKAnnotationViewDragState, fromOldState oldState: MKAnnotationViewDragState) {
}
but it is calling after position change and its view.annotaion.coordinates are read only. I can not reset them...
Please let me know if this is possible using MKMapView? Any possible way to achieve?
Related
I have an MGLPolyline on a mapbox map and want to make is so when the user taps on the line it centers around the line and zooms in as much as possible so that the full line is on display. Currently, I make the centering work well but the zoom works randomly:
I just set it to max zoom, However, this is of course not what I want.
Bellow is where I want to add the zoom amount:
func mapView(_ mapView: MGLMapView, didSelect annotation: MGLAnnotation) {
print("Tapped")
mapView.setCenter(CLLocationCoordinate2D(latitude: annotation.coordinate.latitude, longitude: annotation.coordinate.longitude), zoomLevel: mapView.zoomLevel, animated: true)
mapView.deselectAnnotation(annotation, animated: false)
}
MGLMapView actually has a baked in method specifically for this purpose. You should be able to implement the functionality using -showAnnotations:animated. If you want to fiddle around with the padding around your polyline, you can also use the showAnnotations:edgePadding:animated flavor of the method.
This would look like the following:
func mapView(_ mapView: MGLMapView, didSelect annotation: MGLAnnotation) {
mapView.showAnnotations(pointAnnotations, animated: true)
}
Swift 4 iOS 11.x
Learning about mapViews and annotations and I can quite get my mind around some functionality I would like to do.
I create a mapView, and I add an annotation to it with a button, so far so good. I want the button to be a delete pin one, so it looks like this.
Now when I click on the blue no entry I want it to delete the black pin that it is connected too. But how to trace the link of the annotation to its pin. I get a call back with the button and thru the accessory view. I can lookup the title of the view and find the link, but surely there is a better method.
You need to use this method func mapView(_ mapView: MKMapView,annotationView view: MKAnnotationView,calloutAccessoryControlTapped control: UIControl) of MKMapViewDelegate
Something like this
func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView,
calloutAccessoryControlTapped control: UIControl) {
//Here you have the annotation that was selected
let selectedAnnotation = view.annotation
//Do whatever you need here
}
I have been stuck on this issue for the past day. I have created a custom MKAnnotation subclass to display various custom pins on an MKMapView. I recursively call a function that keeps animating these pins around the map. My goal is to stop all of these animations in place when the user taps on a button. I have tried
self.view.layer.removeAllAnimations()
and
self.map.layer.removeAllAnimations()
and other hacky solutions, but none seem to work.
Below is the code that creates the animation/pin movement
func animate(duration:Double, newLocation:CLLocationCoordinate2D){
UIView.animate(withDuration: duration, animations: {
self.coordinate = newLocation
}) { (done) in
self.finished_segment()
}
}
Any suggestions are much appreciated.
For anyone stuck on this issue. The problem was that I had to remove the animation from the MKAnnotationView associated with the annotation. I basically created a member variable in the custom class that I set in the mapView annotation delegate method as seen below.
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
let annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: "annotationView") ?? MKAnnotationView()
if let a = annotation as? Alien{
annotationView.image = a.image
a.annotationView = annotationView
}
return annotationView
}
And to remove the animation from the map. Simply call
self.annotationView.layer.removeAllAnimations()
I'm trying out mapbox (using the ios sdk) and I've run into a problem that I think I've narrowed down pretty far. This is my code:
func centerMap(location: CLLocationCoordinate2D) {
map.setCenterCoordinate(location,
zoomLevel: 14,
animated: true)
}
func mapView(mapView: MGLMapView, didDeselectAnnotation annotation: MGLAnnotation) {
dealDetails.hidden = false
}
func mapView(mapView: MGLMapView, didUpdateUserLocation userLocation: MGLUserLocation?) {
if let currentLocation = userLocation?.coordinate {
centerMap(currentLocation)
}
}
If I don't re-center the map when the user's location is updated (i.e., just commenting out the centerMap(currentLocation) call) then the annotation remains selected. Re-centering the map calls the didDeselectAnnotation function, and I can't figure out how to keep that annotation selected. Any help is appreciated!
I don't think there's any way around that if you update the center coordinate. You'd have to re-select the annotation. However, you probably don't need to do that. If you set the userTrackingMode on the map view to .Follow, it should re-center automatically.
How do I make it possible, using MapKit in Swift, for the user to drag an annotation from one position to another within the map? I have set the annotation view to be draggable, when my map view delegate creates the annotation view, like this:
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
var v : MKAnnotationView! = nil
if annotation is MyAnnotation {
let ident = "bike"
v = mapView.dequeueReusableAnnotationView(withIdentifier:ident)
if v == nil {
v = MyAnnotationView(annotation:annotation, reuseIdentifier:ident)
}
v.annotation = annotation
v.isDraggable = true
}
return v
}
The result is that the user can sort of drag the annotation - but only once. After that, the annotation becomes impossible to drag, and even worse, the annotation now no longer "belongs" to map - when the map is scrolled / panned, the annotation holds still rather than scrolling / panning with the map. What am I doing wrong?
It isn't enough to mark the annotation view by setting isDraggable to true. You must also implement mapView(_:annotationView:didChange:fromOldState:) in your map view delegate - and (even more important) this implementation must not be empty! Rather, your implementation must, at a minimum, communicate the drag state from the incoming parameters to the annotation view, like this:
func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView, didChange newState: MKAnnotationViewDragState, fromOldState oldState: MKAnnotationViewDragState) {
switch newState {
case .starting:
view.dragState = .dragging
case .ending, .canceling:
view.dragState = .none
default: break
}
}
Once you do that, the annotation will be properly draggable by the user.
(Many thanks to this answer for explaining this so clearly. I can't claim any credit! My answer here is merely a translation of that code into Swift.)