Mapkit annotation anchor point - swift

I'm using a custom image for MapKit annotations using :
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {}
The "pin" shows with the right image now when I add a new annotation to my map, but it seems to use the horizontal and vertical centre of the image as the pin point. Is it possible to make this the bottom centre of the image? I could create a new image thats double the hight with the bottom being blank, but was hoping I could do this programmatically
Thanks

Related

SwiftUI MapKit - Multiple annotations in same map

I've had a look at similar questions but nothing seems to answer this question exactly.
I have a Map view and I want to add pin overlays, as well as a poly line route overlay on top of it. I am very very new at SwiftUI dev (this is my first app), so some help would be appreciated.
At the moment the map only renders the pins, and not the overlay. I'm assuming they need to be put into the same method but cannot figure out how you can return multiple overlays to the mapView.
Here is the Coordinator code:
class Coordinator: NSObject,MKMapViewDelegate{
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
//draw pins
if annotation.isKind(of: MKUserLocation.self){return nil}
else{
let pinAnnotation = MKPinAnnotationView(annotation: annotation, reuseIdentifier: "PIN_VIEW")
pinAnnotation.tintColor = .red
pinAnnotation.animatesDrop = true
pinAnnotation.canShowCallout = true
return pinAnnotation
}
}
private func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKPolylineRenderer? {
//draw route
let render = MKPolylineRenderer(overlay: overlay)
render.strokeColor = .orange
render.lineWidth = 2
return render;
}
}
Here is the output: (no route is drawn). I tried to put the annotations within the same method but couldn't figure out how to return both at the same time (pins are of type MKAnnotationView and the route is of type MKPolylineRenderer...
Help would be really appreciated. Thanks
It should be a separate method, but it shouldn’t be private. Also, the return type should be MKOverlayRenderer.

Adding MKAnnotation to MKMapView above location, not in center

I have this code in MapView Coordinator class for adding annotation to map:
func mapView(_ mapview: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
return mapview.dequeueReusableAnnotationView(withIdentifier: "myiconid")
}
Annotation added in center of my location :
How can I add annotation above my location?
The documentation says:
By default, the center point of an annotation view is placed at the coordinate point of the associated annotation. You can use this property to reposition the annotation view as needed. This x and y offset values are measured in points. Positive offset values move the annotation view down and to the right, while negative values move it up and to the left.
https://developer.apple.com/documentation/mapkit/mkannotationview/1452144-centeroffset
So you might want to change the centerOffset attribute for your annotations...
Annotation are set on the latitude and longitude that you provide while making it. I think there is no means we can place our annotation above our location unless we change our latitude and longitude.

MKAnnotationView tap on title

I want to customize my annotation view to show something like the image below. My questions are:
1) How can I customize the annotation view?
2) How can I make the app do something when user tap on the title? or tapped anywhere in the annotation view? if making it specific to the title is not possible!
I have added
func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl)
but it does not get called!

taxify like pin on map "swift

I have tried the search query above on Bing and Google but got nothing close to my need.
How do implement the taxify/Uber like Pin dropped in the middle of the Google map and obtain location info as the user moves around using swift?
Thanks for your usual support.
You can put the pin as any imageView in the middle of the google map (Above it) , and obtain new center location when user drags the map with
func mapView(_ mapView: GMSMapView, didChange position: GMSCameraPosition) {
print("\(position.target.latitude),\(position.target.longitude)")
}
func mapView(_ mapView: GMSMapView, idleAt position: GMSCameraPosition) {
print("\(position.target.latitude),\(position.target.longitude)")
}

Get LAT and LONG from tapped overlay in Google Maps

When a user taps an overlay, the following code is triggered:
func mapView(_ mapView: GMSMapView, didTap overlay: GMSOverlay) {
}
I wonder if we can extract the exact LAT and LONG coordinates of the overlay that has been tapped?
Thanks!
To solve this we need the 2 methods together,
So I combined them in a way I hope it will help in this issue:
func mapView(_ mapView: GMSMapView, didTap overlay: GMSOverlay) {
print(overlay)
}
func mapView(_ mapView: GMSMapView, didTapAt coordinate: CLLocationCoordinate2D) {
print(coordinate)
for polyline in polylines {
if GMSGeometryIsLocationOnPath(coordinate, polyline.path!, true) {
self.mapView(mapView, didTap: polyline)
}
}
for polygon in polygons {
if GMSGeometryContainsLocation(coordinate, polygon.path!, true) {
self.mapView(mapView, didTap: polygon)
}
}
}
if the user clicked at coordinate we will deal with this, Then check if this coordinate is contained in any Polyline or Polygon we had defined before, So we fire the event didTap overlay for that overlay.
Make sure to make polylines and polygons isTappable = false
And but in mind this event will be fired for every overlay tapped even though if they are overlaped, You can put return when the if success to take the first overlay only
You can use didTapAt delegate method for the same.
#wajih, for you did the method didTapAt was called when you tap on landmark names or titles? For me it's not getting called.
For my case the landmark title is above the polygon and the didTapAt method is not getting called, but if i set tappable to true then didTap(overlay) is called perfectly.
If you just want to get the exact coordinates wherever you tapped whether on Overlay or not, then there is another delegate of GMSMapViewDelegate which is called whenever we tap on GoogleMaps. In this delegate you can get the exact coordinates where you tapped on map irrespective of tapping on an overlay.
Swift 3.0
func mapView(_ mapView: GMSMapView, didTapAt coordinate: CLLocationCoordinate2D) {
print(coordinate.latitude)
print(coordinate.longitude)
}
If you want to get the coordinate only on tapping marker, then use this delegate method
func mapView(_ mapView: GMSMapView, didTap marker: GMSMarker) -> Bool {
print(marker.position.latitude)
print(marker.position.longitude)
return true
}
Make sure to make your overlay as non-tappable
overlay.isTappable = false
For reference see here