Finestra di informazioni personalizzate per Google Maps

Mi piacerebbe creare una finestra informativa personalizzata per Google Maps per iOS come la foto qui sotto. È ansible estendere GMSOverlay come GMSMarker, GMSPolyline e GMSPolygon per creare grafica personalizzata?

inserisci la descrizione dell'immagine qui

Per coloro che stanno cercando di aggiungere pulsanti a una vista personalizzata che rappresenta la finestra informativa, sembra imansible farlo, perché Google Maps SDK lo disegna come un’immagine o qualcosa del genere. Ma c’è una soluzione abbastanza semplice:

  1. Devi creare una visualizzazione personalizzata con pulsanti e tutto ciò che devi mostrare nella finestra delle informazioni.
  2. Aggiungilo come sottoview nel metodo mapView (mapView: GMSMapView, didTapMarker marker: GMSMarker) . Puoi impostare una posizione di una vista personalizzata ottenendo le coordinate di un marker toccato con l’aiuto di mapView.projection.pointForCoordinate (marker.position)
  3. È ansible che la vista personalizzata debba cambiarla posizione seguendo la posizione della telecamera, quindi è necessario gestire mapView (mapView: GMSMapView, didChangeCameraPosition position: GMSCameraPosition) in cui è ansible aggiornare facilmente la posizione della vista personalizzata.

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

Dovrai utilizzare il metodo di delega markerInfoWindow insieme all’impostazione di infoWindowAnchor .

Quando crei il tuo marcatore, imposta l’ancora:

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

quindi creare il metodo delegato:

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

Nell’esempio sopra ho creato uno xib inserisci la descrizione dell'immagine qui e ho caricato quel xib, restituendo l’ UIView risultante. Potresti invece build un UIView usando solo il codice.

Puoi passare questo tipo di UIIimmagine come icona come sotto

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

Per maggiori dettagli vedi questa documentazione .

Se si desidera questo tipo di immagine dopo aver premuto il marcatore, è necessario disporre di due tipi di immagini di un singolo luogo.

Solo 1 icona del contrassegno immagine.

La seconda immagine è un marker con il dettaglio del luogo.

icona del marker caricata quando mapView inizializza come sopra il codice.

E il marcatore Second Image con i dettagli del luogo che devi caricare come questo all’interno del marker premuto metodo delegate usando For-Loop e NSMutablearray controllando marker.title per sapere quale marker è premuto.

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

Versione rapida, versione di esempio della class personalizzata del marcatore:

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

Grazie a Come inizializzare una class UIView con un file xib in Swift, iOS puoi aggiungere l’estensione a UIView in modo da non aver bisogno di 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 } } 

E nel tuo delegato:

  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 }