How to Add Two or More Buttons to Annotationview: Mkannotationview

How to add two or more buttons to annotationView: MKAnnotationView?

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

Result

How to add different button action to the second annotation /pin in map view using swift2

The simplest way to know on which annotation you tap is using creating custom annotation class and adding annotation of it. So create one annotation class MyAnnotation child class of MKPointAnnotation and maintain one uniqueId with your multiple annotation.

class MyAnnotation: MKPointAnnotation {
var uniqueId: Int!
}

Now you need to add annotation of type MyAnnotation instead of MKPointAnnotation.

let annotation = MyAnnotation()
annotation.coordinate = locations
annotation.title = "Zaid Homes"
annotation.subtitle = "Hay aljameaa"
//Set uniqueId for annotation
annotation.uniqueId = 1
map.addAnnotation(annotation)

let annotation2 = MyAnnotation()
annotation2.coordinate = location2
annotation2.title = "Zaid "
annotation2.subtitle = "aljameaa"
//Set uniqueId for annotation
annotation2.uniqueId = 2
map.addAnnotation(annotation2)

Now check this uniqueId in calloutAccessoryControlTapped method on which annotation you tapped.

func mapView(_ mapView: MKMapView, annotationView view:  MKAnnotationView, calloutAccessoryControlTapped control: UIControl) {

if (control as? UIButton)?.buttonType == UIButtonType.detailDisclosure {
mapView.deselectAnnotation(view.annotation, animated: false)
if let myAnnotation = view.annotation as? MyAnnotation {
if (myAnnotation.uniqueId == 1) {
performSegue(withIdentifier: "info1", sender: view)
}
else {
performSegue(withIdentifier: "info2", sender: view)
}
}
}
}

How to add a button to an annotation, current solution not working

You need to add the delegate MKMapViewDelegate. And use the function,

func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) {

}

How to add a button to the MKPointAnnotation?

You are doing it right.You just need to have these methods implemented for adding button along with title and subtitle

iOS 8 and Xcode 6

 import UIKit
import MapKit
import CoreLocation

class MapKitViewController: UIViewController, MKMapViewDelegate
{
let locationManager = CLLocationManager()
@IBOutlet weak var nmapView: MKMapView!
override func viewDidLoad()
{
super.viewDidLoad()
locationManager.requestWhenInUseAuthorization()
locationManager.startUpdatingLocation()
let location = CLLocationCoordinate2D(
latitude: 53.4265107,
longitude: 14.5520357)

let span = MKCoordinateSpanMake(0.05, 0.05)
let region = MKCoordinateRegion(center: location, span: span)
nmapView.setRegion(region, animated: true)
nmapView.showsPointsOfInterest = false
nmapView.showsUserLocation = true
displayMarkers()
}

// When user taps on the disclosure button you can perform a segue to navigate to another view controller
func mapView(mapView: MKMapView!, annotationView view: MKAnnotationView!, calloutAccessoryControlTapped control: UIControl!) {
if control == view.rightCalloutAccessoryView{
println(view.annotation.title) // annotation's title
println(view.annotation.subtitle) // annotation's subttitle

//Perform a segue here to navigate to another viewcontroller
// On tapping the disclosure button you will get here
}
}

// Here we add disclosure button inside annotation window
func mapView(mapView: MKMapView!, viewForAnnotation annotation: MKAnnotation!) -> MKAnnotationView! {

println("viewForannotation")
if annotation is MKUserLocation {
//return nil
return nil
}

let reuseId = "pin"
var pinView = mapView.dequeueReusableAnnotationViewWithIdentifier(reuseId) as? MKPinAnnotationView

if pinView == nil {
//println("Pinview was nil")
pinView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
pinView!.canShowCallout = true
pinView!.animatesDrop = true
}

var button = UIButton.buttonWithType(UIButtonType.DetailDisclosure) as UIButton // button with info sign in it

pinView?.rightCalloutAccessoryView = button

return pinView
}

func displayMarkers() -> Void
{
let jsonURL: NSURL = NSURL(string: "http://atnight.wtznc.com/json.php")!

var dataFromNetwork: NSData = NSData(contentsOfURL: jsonURL)!
let json = JSON(data: dataFromNetwork)
var jsonSize = json.count

var todaysDate:NSDate = NSDate()
var dateFormatter:NSDateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
var formattedDate:String = dateFormatter.stringFromDate(todaysDate)

let annotationView = MKAnnotationView()

// Adding button here wont do anything so remove these two lines

let detailButton: UIButton = UIButton.buttonWithType(UIButtonType.DetailDisclosure) as UIButton
annotationView.rightCalloutAccessoryView = detailButton

// For adding button we have to use a method named as viewForAnnotation

for(var i = 0; i < jsonSize; i++)
{
if(json[i]["rozpoczecie"].stringValue == formattedDate)
{
let clubID = json[i]["id_klub"].stringValue
let annotation = MKPointAnnotation()
let (resultSet, err) = SD.executeQuery("SELECT * FROM Clubs WHERE ID = ?", withArgs: [clubID])
if(err != nil){println("blad")}
else
{
for row in resultSet
{
let name = row["Name"]?.asString()
let latitude = row["Latitude"]?.asDouble()
let longitude = row["Longitude"]?.asDouble()
annotation.title = name
var markerLatitude: Double = latitude!
var markerLongitude: Double = longitude!
let location = CLLocationCoordinate2D(latitude: markerLatitude, longitude: markerLongitude)
annotation.setCoordinate(location)
annotation.subtitle = json[i]["nazwa"].stringValue
}
nmapView.addAnnotation(annotation)
}
}
}
}
}

Check out my output.

Sample Image

MKAnnotationView Swift Adding Info button

Am using Xcode 8.1 and Swift 3.0 . For Some reason Delegate methods are not firing until you set delegate in storyboard:

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

let reuseId = "pin"

var pinView = mapView.dequeueReusableAnnotationView(withIdentifier: reuseId) as? MKPinAnnotationView
if pinView == nil {
pinView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
pinView!.canShowCallout = true
pinView!.animatesDrop = true
let calloutButton = UIButton(type: .DetailDisclosure)
pinView!.rightCalloutAccessoryView = calloutButton
pinView!.sizeToFit()
}
else {
pinView!.annotation = annotation
}

return pinView
}

for button Action

func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) {
if control == view.rightCalloutAccessoryView {
print("button tapped")
}
}

I am attaching sample project for your issue

Map Sample Project Swift 3. 0 Xcode 8.1



Related Topics



Leave a reply



Submit