Подтвердить что ты не робот

Окно пользовательской информации для Карт Google

Я хотел бы создать пользовательское информационное окно для Карт Google для iOS, как на фотографии ниже. Можно ли расширить GMSOverlay, например GMSMarker, GMSPolyline и GMSPolygon, для создания пользовательской графики?

enter image description here

4b9b3361

Ответ 1

Для тех, кто пытается добавить кнопки к пользовательскому представлению, представляющему информационное окно, это кажется невозможным, потому что SDK Google Maps рисует его как изображение или что-то в этом роде. Но есть довольно простое решение:

  • Вам необходимо создать пользовательский вид с кнопками и все, что вам нужно отобразить в информационном окне.
  • Добавьте его в качестве подзадачи в свой метод mapView (mapView: GMSMapView, didTapMarker: GMSMarker). Вы можете установить позицию пользовательского представления, получив координаты маркера, нажатого с помощью mapView.projection.pointForCoordinate(marker.position)
  • Возможно, вам нужно изменить свое положение, следуя позиции камеры, поэтому вам нужно обработать mapView (mapView: GMSMapView, didChangeCameraPosition position: 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

Вы хотите использовать метод делегата 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 enter image description here и я загрузил этот xib, возвращая результирующий UIView. Вместо этого вы можете построить UIView, используя только код.

Ответ 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
 {

 }

Ответ 4

Версия 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
}}

Благодаря Как инициализировать класс UIView с xib файлом в 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
}