Ventana de información personalizada para Google Maps

Me gustaría crear una ventana de información personalizada para Google Maps para iOS, como la foto a continuación. ¿Es posible extender GMSOverlay como GMSMarker, GMSPolyline y GMSPolygon do para crear gráficos personalizados?

enter image description here

Para aquellos que intentan agregar botones a una vista personalizada que representa la ventana de información, parece ser imposible de hacer, porque el SDK de Google Maps lo dibuja como una imagen o algo como esto. Pero hay una solución bastante simple:

  1. Tienes que crear una vista personalizada con botones y lo que necesites que se muestre en tu ventana de información.
  2. Agréguelo como una subvista en su método mapView (mapView: GMSMapView, didTapMarker marker: GMSMarker) . Puede establecer una posición de una vista personalizada obteniendo las coordenadas de un marcador tocado con la ayuda de mapView.projection.pointForCoordinate (marker.position)
  3. Es posible que su vista personalizada tenga que cambiar su posición siguiendo la posición de la cámara, por lo que debe manejar mapView (mapView: GMSMapView, didChangeCameraPosition position: GMSCameraPosition) donde puede actualizar fácilmente su posición de vista personalizada.

    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) } } 

markerInfoWindow utilizar el método de delegado markerInfoWindow junto con la configuración de infoWindowAnchor .

Cuando creas tu marcador, establece el anclaje:

 GMSMarker *marker = [[GMSMarker alloc] init]; marker.position = MARKER_POSITION; marker.infoWindowAnchor = CGPointMake(0.44f, 0.45f); marker.icon = [UIImage imageNamed:@"CustomMarkerImageName"]; 

luego crea el método de delegado:

 - (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; } 

En el ejemplo anterior, creé un xib enter image description here y cargué ese xib, devolviendo el UIView resultante. En su lugar, podría construir una UIView utilizando solo código.

Puedes pasar este tipo de UIImage como un icono como debajo

  CLLocationCoordinate2D position = CLLocationCoordinate2DMake(latitude,longitude); GMSMarker *location = [GMSMarker markerWithPosition:position]; location.title = @"Location Name"; location.icon = [UIImage imageNamed:@"marker_icon.png"]; location.map = mapView_; 

Para más detalles vea esta Documentación .

Si desea este tipo de imagen después de presionar un marcador, debe tener dos tipos de imágenes de un solo lugar.

1er icono de marcador de imagen solamente.

La segunda imagen es marcador con detalle de lugar.

icono marcador cargado cuando mapView inicializa como el código anterior.

Y el marcador de Segunda Imagen con el detalle de lugar que tiene que cargar como este dentro del método de delegate presionado marcador utilizando For-Loop y NSMutablearray marcando marker.title para saber qué marcador se presiona.

  - (BOOL)mapView:(GMSMapView *)mapView didTapMarker:(GMSMarker *)marker { } 

Versión Swift, versión de ejemplo de la clase personalizada de marcador:

 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 }} 

Gracias a Cómo inicializar una Clase UIView con un archivo xib en Swift, iOS puedes agregar extensiones a UIView para que no necesites el lanzamiento

 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 } } 

Y en tu delegado:

  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 }