我想为Google Maps for iOS制作一个自定义信息窗口,如下图所示。是否有可能像GMSMarker,GMSPolyline和GMSPolygon那样扩展GMSOverlay以创建自定义图形?
答案 0 :(得分:105)
您需要使用markerInfoWindow
委托方法并设置infoWindowAnchor
。
创建标记时,请设置锚点:
GMSMarker *marker = [[GMSMarker alloc] init];
marker.position = MARKER_POSITION;
marker.infoWindowAnchor = CGPointMake(0.44f, 0.45f);
marker.icon = [UIImage imageNamed:@"CustomMarkerImageName"];
然后创建委托方法:
- (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;
}
在上面的例子中,我创建了一个xib
然后我加载了xib,返回结果UIView
。您可以使用代码构建UIView
。
答案 1 :(得分:7)
对于那些试图将按钮添加到代表信息窗口的自定义视图的人来说 - 似乎无法做到,因为Google Maps SDK会将其绘制为图像或类似内容。但是有一个非常简单的解决方案:
您的自定义视图可能需要按照摄像头位置更改位置,因此您必须处理 mapView(mapView:GMSMapView,didChangeCameraPosition位置:GMSCameraPosition),您可以在其中轻松更新自定义查看位置。
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)
}
}
答案 2 :(得分:3)
您可以将此类型的UIImage传递为如下图标
CLLocationCoordinate2D position = CLLocationCoordinate2DMake(latitude,longitude);
GMSMarker *location = [GMSMarker markerWithPosition:position];
location.title = @"Location Name";
location.icon = [UIImage imageNamed:@"marker_icon.png"];
location.map = mapView_;
如果在按下标记后想要这种类型的图像,则必须有两种类型的单一图像。
仅限第一个图像标记图标。
第二张图片是带有地方细节的标记。
当mapView初始化时加载标记图标,如上面的代码。
带有地方详细信息的第二个图片标记,您必须使用delegate
和For-Loop
方法在标记内按NSMutablearray
方法加载,方法是检查marker.title
以了解按下了哪个标记
- (BOOL)mapView:(GMSMapView *)mapView didTapMarker:(GMSMarker *)marker
{
}
答案 3 :(得分:2)
Swift版本,标记自定义类的示例版本:
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
}}
感谢How to initialise a UIView Class with a xib file in Swift, iOS您可以为UIView添加扩展程序,因此您不需要强制转换
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
}
}
在你的代表中:
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
}