I'd like to make a custom Info Window for Google Maps for iOS like the photo below. Is it possible to extend GMSOverlay like GMSMarker, GMSPolyline, and GMSPolygon do to create custom graphics?
-
Custom info window (== window on click) OR custom marker (==always there)? – Daij-Djan May 25 '13 at 08:33
-
1http://kevinxh.github.io/swift/custom-and-interactive-googlemaps-ios-sdk-infowindow.html this blog explains how to solve this problem. – Kevin He Nov 12 '16 at 02:07
-
Please mark the accepted answer. – Efren Aug 10 '17 at 04:59
4 Answers
You will want to use the markerInfoWindow
delegate method along with setting the infoWindowAnchor
.
When you create your marker, set the anchor:
GMSMarker *marker = [[GMSMarker alloc] init];
marker.position = MARKER_POSITION;
marker.infoWindowAnchor = CGPointMake(0.44f, 0.45f);
marker.icon = [UIImage imageNamed:@"CustomMarkerImageName"];
then create the delegate method:
- (UIView *)mapView:(GMSMapView *)mapView markerInfoWindow:(GMSMarker *)marker {
InfoWindow *view = [[[NSBundle mainBundle] loadNibNamed:@"InfoWindow" owner:self options:nil] objectAtIndex:0];
view.name.text = @"Place Name";
view.description.text = @"Place description";
view.phone.text = @"123 456 789";
view.placeImage.image = [UIImage imageNamed:@"customPlaceImage"];
view.placeImage.transform = CGAffineTransformMakeRotation(-.08);
return view;
}
In the example above I created a xib
and I loaded that xib, returning the resulting
UIView
. You could instead construct a UIView
using just code.
-
skarE, did you also have to make a corresponding InfoWindow class? Would it be possible to get a copy of the XIB file you made? Thanks! – Charlie J Dec 20 '13 at 20:26
-
3
-
-
1@RahulMishra the info window is a rendered version of the UIView, which is why the view does not recognise user interaction – henrik-dmg Feb 21 '17 at 19:01
-
-
Hello all, when i am trying to add custom infowindow in my google map view then i am getting following error. This NSLayoutConstraint is being configured with a constant that exceeds internal limits. A smaller value will be substituted, but this problem should be fixed. Break on BOOL _NSLayoutConstraintNumberExceedsLimit(void) to debug. This will be logged only once. This may break in the future. Any help – Ravi Kumar Jan 11 '18 at 04:54
For those who's trying to add buttons to a custom view representing info window - it seems to be impossible to do, because Google Maps SDK draws it as an image or something like this. But there is a quite simple solution:
- You have to create a custom view with buttons and whatever you need to be displayed in your info window.
- Add it as a subview in your mapView(mapView: GMSMapView, didTapMarker marker: GMSMarker) method. You can set a position of a custom view by getting a coordinates of a marker tapped with a help of mapView.projection.pointForCoordinate(marker.position)
Your custom view possibly has to change it position by following camera position, so you have to handle mapView(mapView: GMSMapView, didChangeCameraPosition position: GMSCameraPosition) where you could easily update your custom view position.
var infoWindow = CustomInfoView() var activePoint : POIItem? func mapView(mapView: GMSMapView, didTapMarker marker: GMSMarker) -> Bool { if let poiItem = marker as? POIItem { // Remove previously opened window if any if activePoint != nil { infoWindow.removeFromSuperview() activePoint = nil } // Load custom view from nib or create it manually // loadFromNib here is a custom extension of CustomInfoView infoWindow = CustomInfoView.loadFromNib() // Button is here infoWindow.testButton.addTarget(self, action: #selector(self.testButtonPressed), forControlEvents: .AllTouchEvents) infoWindow.center = mapView.projection.pointForCoordinate(poiItem.position) activePoint = poiItem self.view.addSubview(infoWindow) } return false } func mapView(mapView: GMSMapView, didChangeCameraPosition position: GMSCameraPosition) { if let tempPoint = activePoint { infoWindow.center = mapView.projection.pointForCoordinate(tempPoint.position) } }

- 114
- 2
- 3
-
Default information window also shown. and how to show indicator on custom information pointing to clicked marker. – Raj Aggrawal Jun 06 '17 at 13:00
-
-
@King It may be your wrapper class to contain coordinates and name, for example. It has to be the subclass of GMSMarker. Have a look [here](https://developers.google.com/maps/documentation/ios-sdk/utility/marker-clustering) – Yuri Grigoriev Jun 01 '19 at 13:13
-
The tool tip has its own background which is white. Can I make it clear ? Because I’ve tried and nothing seems to be working – King Jun 01 '19 at 13:28
-
I guess it should work as it is usual subview you add to your ViewController's view, but I cannot check this at the moment. – Yuri Grigoriev Jun 01 '19 at 14:05
-
-
Sure, just assign to infoWindow your UIView created programmatically. – Yuri Grigoriev Jun 01 '19 at 18:04
You can pass this type of UIImage as icon like below
CLLocationCoordinate2D position = CLLocationCoordinate2DMake(latitude,longitude);
GMSMarker *location = [GMSMarker markerWithPosition:position];
location.title = @"Location Name";
location.icon = [UIImage imageNamed:@"marker_icon.png"];
location.map = mapView_;
For more details see this Documentation.
If you want this type of image after marker pressed than you must have two type of images of single place.
1st image marker icon only.
2nd image is marker with place detail.
marker icon loaded when mapView initialise like above code.
And Second Image marker with place detail you have to load like this inside marker pressed delegate
method using For-Loop
and NSMutablearray
by checking marker.title
to know which marker is pressed.
- (BOOL)mapView:(GMSMapView *)mapView didTapMarker:(GMSMarker *)marker
{
}

- 1,042
- 13
- 19
-
Yeah I've seen that but I'm looking to customize the whole Info Window when the user touches a marker. – jspooner May 25 '13 at 14:09
Swift version, example version of marker custom class:
class CustomMarker: UIView {
@IBOutlet weak var titleLabel: UILabel!
@IBOutlet weak var seperator: UIImageView!
@IBOutlet weak var icon: UIImageView!
@IBOutlet weak var descriptionLabel: UILabel!
class func instanceFromNib() -> UIView {
return UINib(nibName: "CustomMarker", bundle: nil).instantiateWithOwner(nil, options: nil)[0] as! UIView
}}
Thanks to How to initialise a UIView Class with a xib file in Swift, iOS you can add extension to UIView so you don't need cast
protocol UIViewLoading {}
extension UIView : UIViewLoading {}
extension UIViewLoading where Self : UIView {
// note that this method returns an instance of type `Self`, rather than UIView
static func loadFromNib() -> Self {
let nibName = "\(self)".characters.split{$0 == "."}.map(String.init).last!
let nib = UINib(nibName: nibName, bundle: nil)
return nib.instantiateWithOwner(self, options: nil).first as! Self
}
}
And in your delegate:
func mapView(mapView: GMSMapView, markerInfoWindow marker: GMSMarker) -> UIView? {
let customMarker:CustomMarker = CustomMarker.loadFromNib()
customMarker.titleLabel.text = marker.title
customMarker.descriptionLabel.text = marker.snippet
return customMarker
}

- 1
- 1

- 3,785
- 1
- 30
- 44