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