Fenêtre d’informations personnalisées pour Google Maps

Je voudrais créer une fenêtre d’informations personnalisée pour Google Maps pour iOS, comme la photo ci-dessous. Est-il possible d’étendre GMSOverlay comme GMSMarker, GMSPolyline et GMSPolygon pour créer des graphiques personnalisés?

entrer la description de l'image ici

Pour ceux qui essaient d’append des boutons à une vue personnalisée représentant une fenêtre d’informations, cela semble impossible, car le SDK de Google Maps le dessine comme une image ou quelque chose du genre. Mais il existe une solution assez simple:

  1. Vous devez créer une vue personnalisée avec des boutons et tout ce que vous devez afficher dans votre fenêtre d’informations.
  2. Ajoutez-le en tant que sous-vue dans votre méthode mapView (mapView: GMSMapView, didTapMarker marker: GMSMarker) . Vous pouvez définir la position d’une vue personnalisée en obtenant les coordonnées d’un marqueur à l’aide de mapView.projection.pointForCoordinate (marker.position)
  3. Votre vue personnalisée doit éventuellement la modifier en suivant la position de la caméra. Vous devez donc gérer mapView (mapView: GMSMapView, position didChangeCameraPosition: GMSCameraPosition) où vous pouvez facilement mettre à jour votre position d’affichage personnalisée.

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

Vous souhaiterez utiliser la méthode delegate infoWindowAnchor avec la définition de infoWindowAnchor .

Lorsque vous créez votre marqueur, définissez l’ancre:

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

puis créez la méthode déléguée:

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

Dans l’exemple ci-dessus j’ai créé un xib entrer la description de l'image ici et j’ai chargé cette xib, retournant le UIView résultant. Vous pouvez à la place construire un UIView utilisant juste du code.

Vous pouvez passer ce type d’UIImage en tant qu’icône comme ci-dessous

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

Pour plus de détails, voir cette documentation .

Si vous souhaitez que ce type d’image soit repéré après un marqueur, vous devez disposer de deux types d’images à un seul endroit.

1ère icône de marqueur d’image uniquement.

La 2ème image est un marqueur avec un détail de lieu.

icône de marqueur chargée lors de l’initialisation de mapView comme ci-dessus.

Et le marqueur Second Image avec les détails de lieu que vous devez charger comme cette méthode delegate aide d’un marqueur à l’aide de For-Loop et NSMutablearray en vérifiant marker.title pour savoir quel marqueur est pressé.

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

Version rapide, exemple de version de la classe personnalisée du marqueur:

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

Grâce à comment initialiser une classe UIView avec un fichier xib dans Swift, iOS, vous pouvez append une extension à UIView pour que vous n’ayez pas besoin de lancer

 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(Ssortingng.init).last! let nib = UINib(nibName: nibName, bundle: nil) return nib.instantiateWithOwner(self, options: nil).first as! Self } } 

Et chez votre délégué:

  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 }