I want to have a MKAnnotationView to my pins on map (using MapKit) with next attributes:
1) image
2) details button
3) another details button
4) another details button?
I have done actually adding image and details button with next code:
annotationView.detailCalloutAccessoryView = snapshotView // snapshot view is a custom view
// with image and its constraints
let detailsButton = UIButton(type: .detailDisclosure)
annotationView.rightCalloutAccessoryView = detailsButton
So, the question is how to add more than one button to MKAnnotationView
?
Because all the tutorials that I've ever seen only is "how to add details button".
You can use detailCalloutAccessoryView
of the MKAnnotationView
to achieve that.
Example how to do extension of the MKAnnotationView
with UIStackView
:
extension MKAnnotationView {
func conteiner(arrangedSubviews: [UIView]) {
let stackView = UIStackView(arrangedSubviews: arrangedSubviews)
stackView.axis = .vertical
stackView.distribution = .fillEqually
stackView.alignment = .fill
stackView.spacing = 5
stackView.autoresizingMask = [.flexibleLeftMargin, .flexibleRightMargin, .flexibleLeftMargin, .flexibleBottomMargin, .flexibleWidth, .flexibleHeight]
stackView.translatesAutoresizingMaskIntoConstraints = false
self.detailCalloutAccessoryView = stackView
}
}
And how to implement this:
extension ViewController: MKMapViewDelegate {
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
let annotationIdentifier = "AnnotationIdentifier"
var annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: annotationIdentifier)
if annotationView == nil {
annotationView = MKAnnotationView(annotation: annotation, reuseIdentifier: annotationIdentifier)
annotationView!.canShowCallout = true
annotationView!.conteiner(arrangedSubviews: [UIButton(type: .detailDisclosure), UIButton(type: .detailDisclosure), UIButton(type: .detailDisclosure)])
}
else {
annotationView!.annotation = annotation
}
return annotationView
}
}
I have done it
From documentation left and right calloutAccessoryView are low width and height. So, we can add buttons and image only in detailCalloutAccessoryView.
Here is my code. It's working. I haven't done a review. Because it's more clear for understanding.
func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) {
if !(view.annotation! is MKUserLocation) {
let customPin = view.annotation as! CustomPin
self.spotDetailsForSendToPostsStripController = customPin.spotDetailsItem // its for sending to another controller.
configureDetailView(annotationView: view, spotPin: customPin.spotDetailsItem)
}
}
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
if annotation is MKUserLocation {
return nil
}
if !(annotation is CustomPin) {
return nil
}
let identifier = "CustomPin"
var annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: identifier)
if annotationView == nil {
annotationView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: identifier)
annotationView?.canShowCallout = true
} else {
annotationView!.annotation = annotation
}
return annotationView
}
func configureDetailView(annotationView: MKAnnotationView, spotPin: SpotDetailsItem) {
let width = 250
let height = 250
let snapshotView = UIView()
let views = ["snapshotView": snapshotView]
snapshotView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:[snapshotView(250)]", options: [], metrics: nil, views: views))
snapshotView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:[snapshotView(250)]", options: [], metrics: nil, views: views))
let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: width, height: height - 40))
// configure button1
let button1 = UIButton(frame: CGRect(x: 0, y: height - 35, width: width / 2 - 5, height: 35))
button1.setTitle("Info", for: .normal)
button1.backgroundColor = UIColor.darkGray
button1.layer.cornerRadius = 5
button1.layer.borderWidth = 1
button1.layer.borderColor = UIColor.black.cgColor
button1.addTarget(self, action: #selector(MainFormController.goToInfo), for: .touchDown)
// configure button2
let button2 = UIButton(frame: CGRect(x: width / 2 + 5, y: height - 35, width: width / 2, height: 35))
button2.setTitle("Posts", for: .normal)
button2.backgroundColor = UIColor.darkGray
button2.layer.cornerRadius = 5
button2.layer.borderWidth = 1
button2.layer.borderColor = UIColor.black.cgColor
button2.addTarget(self, action: #selector(MainFormController.goToPosts), for: .touchDown)
// configure image
let image = UIImage(contentsOfFile: "plus-512.gif")
imageView.image = image // implement your own logic
imageView.layer.cornerRadius = imageView.frame.size.height / 10
imageView.layer.masksToBounds = true
imageView.layer.borderWidth = 0
imageView.contentMode = UIViewContentMode.scaleAspectFill
// adding it to view
snapshotView.addSubview(imageView)
snapshotView.addSubview(button1)
snapshotView.addSubview(button2)
annotationView.detailCalloutAccessoryView = snapshotView
}
func goToPosts() {
print("go to posts") // your implementation(segues and etc)
}
func goToInfo() {
print("go to info") // your implementation(segues and etc)
}
CustomPin:
class CustomPin: MKPointAnnotation {
var spotDetailsItem: SpotDetailsItem! // its my info of this place
}
Works like a charm
来源:https://stackoverflow.com/questions/43407978/how-to-add-two-or-more-buttons-to-annotationview-mkannotationview