I am trying to change the default colour of the cluster annotation mapkit for iOS, swift.
Is it possible. I can change the individual annotations but not the cluster.
Below is my code.
#available(iOS 11.0, *)
func mapView(_ mapView: MKMapView, clusterAnnotationForMemberAnnotations memberAnnotations: [MKAnnotation]) -> MKClusterAnnotation {
let vehicles = MKClusterAnnotation(memberAnnotations: memberAnnotations)
vehicles.title = "Photos"
vehicles.subtitle = nil
return vehicles
}
Use markerTintColor.
https://developer.apple.com/documentation/mapkit/mkmarkerannotationview/2873822-markertintcolor
e.g.
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
let identifier = "marker"
var view: MKMarkerAnnotationView
if let dequeuedView = mapView.dequeueReusableAnnotationView(withIdentifier: identifier)
as? MKMarkerAnnotationView {
dequeuedView.annotation = annotation
view = dequeuedView
} else {
view = MKMarkerAnnotationView(annotation: annotation, reuseIdentifier: identifier)
view.markerTintColor = .blue
}
return view
}
Related
I have the following code which works for iOS 13 and lower.
func mapView(_ mapView: MKMapView, didUpdate userLocation: MKUserLocation) {
mapView.userLocation.title = "You are here"
mapView.userLocation.subtitle = // user's location
}
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
if annotation.isKind(of: MKUserLocation.self) {
return nil
}
}
It shows only the blue dot without a callout and above the blue dot is just the title and subtitle.
But on iOS 14 there is a default MKBalloonCalloutView that appears in place of the title and subtitle. It shows a gray profileImage. How can I get rid of the BalloonCallout so I can show just the title and subtitle?
By setting your own detail detailCalloutAccessoryView for the User Location annotation's MKAnnotationView the behaviour reverts to just showing title and subtitle.
You can set any UIView of your choice, like an UIImageView for example, or just an empty one.
For example in your MKMapViewDelegate
func mapViewDidFinishLoadingMap(_ mapView: MKMapView) {
mapView.view(for: mapView.userLocation)?.detailCalloutAccessoryView = .init()
}
For the user (the one from the question), if using iOS 14 and higher I use MKMarkerAnnotationView,. If using iOS 13 or lower I use MKPinAnnotationView. I have a separate custom pin for everyone else:
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
let reuseIdentifier = "MyIdentifier"
if annotation.isKind(of: MKUserLocation.self) {
if #available(iOS 14.0, *) {
if let pin = mapView.dequeueReusableAnnotationView(withIdentifier: MKMapViewDefaultAnnotationViewReuseIdentifier) as? MKMarkerAnnotationView {
return setMKMarkerAnnotationView(pin: pin)
}
} else {
let pin = MKPinAnnotationView(annotation: annotation, reuseIdentifier: reuseIdentifier)
pin.canShowCallout = true
return pin
}
return nil
} else {
// dequeue the custom pins for everyone else
}
}
func setMKMarkerAnnotationView(pin: MKMarkerAnnotationView) -> MKMarkerAnnotationView {
pin.animatesWhenAdded = true
pin.markerTintColor = UIColor.red
pin.titleVisibility = .visible
pin.subtitleVisibility = .visible
return pin
}
So I'm trying to create an app with custom annotations on the map, and I've been following a tutorial on how to do it. However when I put this code in, its giving me the error
Invalid redeclaration of 'mapView(_:viewFor:)'
Here's the tutorial - https://www.youtube.com/watch?v=w_aw72i8P_U
extension ViewController: MKMapViewDelegate {
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
guard let _annotation = annotation as? MyAnnotation else {return }
let identifier = "marker"
var view: MKMarkerAnnotationView
if let dequeuedView = mapView.dequeueReusableAnnotationView(withIdentifier: identifier) as? MKMarkerAnnotationView {
dequeuedView.annotation = annotation
view = dequeuedView
}
else
{
view = MKMarkerAnnotationView(annotation: annotation, reuseIdentifier: identifier)
view.canShowCallout = true
view.calloutOffset = CGPoint(x: -5, y: 5)
view.rightCalloutAccessoryView = UIButton(type: .detailDisclosure)
}
return view
}
}
This normally happens when you already implemented that method elsewhere.
Check your ViewController to make sure you don't have func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {} implemented outside of that extension.
I am trying to get an annotation on the user location but I can't get a (sort of) speech bubble for my annotation's details. Is there any option to create something like this?
//AnnotationSettings
let newPin = MKPointAnnotation()
//set region on the map
maphome.setRegion(region, animated: true)
newPin.coordinate = location.coordinate
newPin.title = "aksldfjaskldfjaklsdfa"
newPin.subtitle = "sounds awesome!"
maphome.addAnnotation(newPin)
This is my code for the annotation.
You should set canShowCallout = true.
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
if annotation is MKUserLocation {
return nil
}
let reuseId = "pin"
var pinView = mapView.dequeueReusableAnnotationView(withIdentifier: reuseId) as? MKMarkerAnnotationView
if pinView == nil {
pinView = MKMarkerAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
pinView?.canShowCallout = true
let rightButton: AnyObject! = UIButton(type: UIButtonType.detailDisclosure)
pinView?.rightCalloutAccessoryView = rightButton as? UIView
}
else {
pinView?.annotation = annotation
}
return pinView
}
yes, you can try this
func mapView(_ mapView: MGLMapView, annotationCanShowCallout annotation: MGLAnnotation) -> Bool {
// Always allow callouts to popup when annotations are tapped.
return true
}
I currently have a custom MKAnnotationView set in a map callout, and it's working well. I however want to add a button to the callout view, but when i tap the button it closes the annotation view before it gets called. How can i get around this?
Here are pertinent bits of my code:
In my view for annotations:
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
if annotation is MKUserLocation {
return nil
}
let reuseId = "mapReuseId"
var mapView = mapView.dequeueReusableAnnotationView(withIdentifier: reuseId)
if mapView == nil {
mapView = MKAnnotationView(annotation: annotation as! Annotation, reuseIdentifier: reuseId)
mapView!.canShowCallout = false
} else {
mapView!.annotation = annotation as! Annotation
}
mapDottView!.image = customImage
return mapDottView
}
In my didSelect delegate:
func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) {
let callOut = customCallOutView(with: data)
view.addSubview(callOut)
// some layout here
}
The customCallOutView is longish, but the important part is that it has a UIButton which never gets called on tap. Any ideas?
You can try to put a delay when your button is tapped.
You can use Grand Central Dispatch or Perform Selector After Delay.
// Do what you need to do when your button was tapped.
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
// Dismiss your annotation.
}
Try the following code:
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
if annotation is MKUserLocation {
return nil
}
let reuseId = "mapReuseId"
var mapView = mapView.dequeueReusableAnnotationView(withIdentifier: reuseId)
if mapView == nil {
mapView = MKAnnotationView(annotation: annotation as! Annotation, reuseIdentifier: reuseId)
mapView!.canShowCallout = true
let rightButton: AnyObject! = UIButton(type: UIButtonType.detailDisclosure)
pinView?.rightCalloutAccessoryView = rightButton as? UIView
} else {
mapView!.annotation = annotation as! Annotation
}
mapDottView!.image = customImage
return mapDottView
}
func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) {
print(#function)
// this method will be called when the button is tapped.
// annotation view doesn't disappear
}
I have a map and on this map I have custom annotation pins. All pins have same custom image. When i click on a pin, i need to change this annotation's image. I was using Google Maps before:
func mapView(_ mapView: GMSMapView, didTap marker: GMSMarker) -> Bool {
if marker.userData as? Int != nil {
let marker_tag = marker.userData as! Int
Datas.selectedMarkerIndex = marker_tag
if let selectedMarker = mapView.selectedMarker {
selectedMarker.icon = UIImage(named: "marker_gray")
}
mapView.selectedMarker = marker
marker.icon = UIImage(named: "marker_red")
}
return true
}
This was working fine. But I dont know how to do it with MapKit. I want to change just selected marker(pin) image. How can I do this?
Also I tried this but not working
How to change non selected annotation pin images on mapkit with Swift
And this is my code:
class CustomPointAnnotation: MKPointAnnotation {
var pinImageName:String!
var userData:Int!
}
extension MyView: MKMapViewDelegate {
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
let reuseIdentifier = "my_pin"
var annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: reuseIdentifier)
if annotationView == nil {
annotationView = MKAnnotationView(annotation: annotation, reuseIdentifier: reuseIdentifier)
} else {
annotationView?.annotation = annotation
}
let customPointAnnotation = annotation as! CustomPointAnnotation
annotationView?.isDraggable = false
annotationView?.canShowCallout = false
annotationView?.layer.anchorPoint = CGPoint(x: 0.5, y: 1)
annotationView?.image = UIImage(named: customPointAnnotation.pinImageName)
return annotationView
}
func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) {
if let anno = view.annotation as? CustomPointAnnotation {
let marker_tag = anno.userData!
print(marker_tag)
}
}
func addMarkersOnMap(){
if Datas.myArray.count != 0 {
Datas.selectedMarkerIndex = 0
for i in 0..<Datas.myArray.count{
let lat = Datas.myArray[i].lat
let lng = Datas.myArray[i].lng
myArray.append(CustomPointAnnotation())
if lat != nil {
let location = CLLocationCoordinate2D(latitude: lat!, longitude: lng!)
myArray[i].pinImageName = "marker_gray"
myArray[i].coordinate = location
myArray[i].userData = i
pinAnnotationView = MKPinAnnotationView(annotation: myArray[i], reuseIdentifier: "my_pin")
mapView.addAnnotation(pinAnnotationView.annotation!)
}
}
"selected" means "tapped"? If so, Try the following code:
func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) {
view.image = UIImage(named: "marker_gray")
}
func mapView(_ mapView: MKMapView, didDeselect view: MKAnnotationView) {
view.image = UIImage(named: "marker_red")
}