I'm using google map and I set markers to my map like this:
var marker = GMSMarker(position: CLLocationCoordinate2D(latitude: Double(item.lat)!, longitude: Double(item.lon)!))
marker.map = mapview
now,I would like to detect when user click on these markers.
How can I do?
you should set your mapview delegate to self UIViewController in viewDidLoad
self.mapview.delegate = self
your UIViewController should
extension ViewControllerClass: GMSMapViewDelegate {
//class code
#objc(mapView:didTapMarker:) func mapView(_: GMSMapView, didTap marker: GMSMarker) -> Bool {
//do something
return true
}
}
maybe this method can be implemented some other way already, but Xcode forced me to make it this way while migrating from Swift 2 to Swift 3
For Swift 3
You can implement GMSMapViewDelegatesomething like this:
extension YourViewConytoller: GMSMapViewDelegate {
func mapView(_ mapView: GMSMapView, didTap marker: GMSMarker) -> Bool {
print ("MarkerTapped Locations: \(marker.position.latitude), \(marker.position.longitude)")
return true
}
}
Related
I have been building a Google Maps iOS app and somehow my 'didTap marker' function does not work. If I tap on a marker on the map, the whole view simply just gets dragged off to left, but no code gets run. Otherwise, the print functions below would work. Where might cause this problem?
func mapView(_ mapView: GMSMapView, didTap marker: GMSMarker){
var lat: CLLocationDegrees = marker.position.latitude
var lng: CLLocationDegrees = marker.position.longitude
var formattedCoordinate = CLLocationCoordinate2D(latitude: lat,longitude: lng)
print("markersArray is \(markersArray)")
print("formattedCoordinate is \(formattedCoordinate)")
markersArray = markersArray.filter({ !(($0.latitude == formattedCoordinate.latitude) && ($0.longitude == formattedCoordinate.longitude)) })
}
You need to set delegate for mapview.
set delegate in viewDidLoad
myGMSMapView.delegate = self
then use this method
func mapView(_ mapView: GMSMapView, didTap marker: GMSMarker) -> Bool {
<#code#>
}
Add this delegate in your class.
GMSMapViewDelegate
Now, this will be your marker action.
func mapView(_ mapView: GMSMapView, didTap marker: GMSMarker) -> Bool {
mapView.delegate = self
print("You tapped : \(marker.position.latitude),\(marker.position.longitude)")
}
I'm using this simple MyMarker class
class MyMarker: GMSMarker {
var id: UInt32 = 0
}
so that my markers can also hold an additional numerical tag. When the user taps on my markers I call a segue to open a new scene the content's of which are dynamic and drawn with respect to the MyMarker's id. I want to do something like:
func mapView(mapView: GMSMapView, didTapMarker marker: MyMarker) -> Bool {
some_global_variable = marker.id;
performSegueWithIdentifier("segue", sender: nil)
return true
}
the problem of course is that the GMSMapViewDelegate expects marker to be of type GMSMarker.
How can I implement the behaviour I am after?
You need to type cast GMSMarker to your custom marker in it's delegate method, don't change signature of GMSMapViewDelegate methods.
func mapView(mapView: GMSMapView, didTapMarker marker: GMSMarker) -> Bool {
if let myMarker = marker as? MyMarker {
some_global_variable = myMarker.id
performSegueWithIdentifier("segue", sender: nil)
}
return true
}
I have a view controller with a GMSMapView and have loaded a number of markers onto the map. I can change which marker is selected with mapView.selectedMarker = ... but how do I change the color of the selected marker?
You can use GMSMarker.markerImage(with: <UIColor?>) to reset a marker's icon.
Docs: Google Maps iOS SDK GMSMarker Class Reference
import GoogleMaps
// view controller
class MapViewController: UIViewController {
// outlets
#IBOutlet weak var mapView: GMSMapView!
// view did load method
override func viewDidLoad() {
super.viewDidLoad()
// set map view delegate
mapView.delegate = self
}
}
// extension for GMSMapViewDelegate
extension MapViewController: GMSMapViewDelegate {
// tap map marker
func mapView(_ mapView: GMSMapView, didTap marker: GMSMarker) -> Bool {
print("didTap marker \(marker.title)")
// remove color from currently selected marker
if let selectedMarker = mapView.selectedMarker {
selectedMarker.icon = GMSMarker.markerImage(with: nil)
}
// select new marker and make green
mapView.selectedMarker = marker
marker.icon = GMSMarker.markerImage(with: UIColor.green)
// tap event handled by delegate
return true
}
}
Simple Way Swift 5
marker.icon = GMSMarker.markerImage(with: UIColor.green)
The accepted answer wasn't working for me because if a user tapped a non-marker on the map, selectedMarker would be set to nil. If the user then tapped another marker, triggering the didTap callback, the selectedMarker would be nil and thus retain its selected state/color.
The fix for me was to remove that selectedMarker logic from didTap and move it to didCloseWindowOf.
Here's the code:
func mapView(_ mapView: GMSMapView, didTap marker: GMSMarker) -> Bool {
marker.icon = UIImage(named: "map_marker_selected")
return false // return false to display info window
}
func mapView(_ mapView: GMSMapView, didCloseInfoWindowOf marker: GMSMarker) {
marker.icon = UIImage(named: "map_marker_unselected")
}
This works because when the user taps a non-marker, the info window closes which triggers didCloseInfoWindowOf.
If you use RxSwift, here is an elegant solution with RxGoogleMaps
Observable.combineLatest(mapView.rx.selectedMarker,
mapView.rx.selectedMarker.skip(1))
.subscribe(onNext: { (old, new) in
old?.icon = GMSMarker.markerImage(with: nil)
new?.icon = GMSMarker.markerImage(with: UIColor.red)
})
.disposed(by: disposeBag)
I know it is possible to capture the taps in the infowindow of a marker. I followed the documentation here.
All are written in Objective C so I tried converting it to Swift, here is my code:
func mapView(_ mapView: GMSMapView, didTap InfoWindowOfMarker: GMSMarker) {
print("You tapped infowindow")
}
But this isn't getting fired at all. What is wrong with the method?
You need to use the delegate of GMSMapView along with some prior setting see below.
Declare the use of GMSMapViewDelegate methods and set the delegate to self:
class yourClassName: UIViewController,GMSMapViewDelegate
mapView?.delegate = self
Method to detect tap on infoWindow:
func mapView(_ mapView: GMSMapView, didTapInfoWindowOf marker: GMSMarker) {
print("infowindow tapped")
}
Method to detect tap on GMSMarker:
func mapView(mapView: GMSMapView, didTapMarker marker: GMSMarker) -> Bool {
print("tapped on marker")
if marker.title == "myMarker"{
print("handle specific marker")
}
return true
}
Method to create custom infoWindow:
func mapView(mapView: GMSMapView!, markerInfoWindow marker: GMSMarker!) -> UIView! {
let infoWindow = Bundle.main.loadNibNamed("nibName", owner: self, options: nil).first as! ClassName
infoWindow.name.text = "title"
infoWindow.address.text = "relevant address"
infoWindow.photo.image = UIImage(named: "imageName")
return infoWindow
}
I customized a infoWindow, but this shows a infowindow default in the background. Is there a way to hide the infoWindow background? or that I'm doing wrong.
The code is:
func mapView(mapView: GMSMapView!, markerInfoContents marker: GMSMarker!) -> UIView! {
if let infoView = UIView.viewFromNibName("MarkerInfoView") as? MarkerInfoView {
infoView.lblTitle.text = "Title" //marker.title
infoView.lblDescription.text = "Description"
infoView.lblDescription.numberOfLines = 0
infoView.lblDescription.lineBreakMode = NSLineBreakMode.ByWordWrapping
infoView.lblDescription.sizeToFit()
return infoView
} else {
return nil
}
}
in your nib file, where you do custom look for your info window, set top nib view background color to clear color
Set your custom view as the marker image instead of the info window.
Convert your custom view into image and set it as marker image.
That will solve your purpose.
I think you need to implement this method and return your custom view.
func mapView(_ mapView: GMSMapView, markerInfoWindow marker: GMSMarker) -> UIView?
make sure that you don't have
marker.title = "something"
anywhere in your code. Then the default will always show unless you use
func mapView(_ mapView: GMSMapView, markerInfoWindow marker: GMSMarker) -> UIView? {
<#code#>
}
to set your infoWindow properties.
If you are using a customInfoWindow, then you don't have to access GMSMarker() properties like marker.snippet and marker.title
Even if you use them by mistake in your code, then you need to return an empty view in delegate method:
func mapView(_ mapView: GMSMapView, markerInfoWindow marker: GMSMarker) -> UIView? {
return UIView()
}