Google Maps iOS didTapInfoWindowOfMarker не срабатывает, когда поверх других маркеров


Я использую последнюю версию GoogleMaps-iOS v1. 3 SDK.

У меня возникли проблемы с запуском didTapInfoWindowOfMarker при нажатии на информационное окно, когда сразу за ним есть несколько других маркеров. Вместо этого, нажатие на информационное окно чаще всего действует так, как если бы вы касались маркера позади него (и открывали другое информационное окно).

В частности, на моей карте у меня есть десятки и десятки GMSMarkers очень близко друг к другу - достаточно близко, чтобы любое всплывающее окно информации покрывало несколько маркеров, даже на самых высоких уровнях масштабирования.

Есть ли способ заставить тапы по информационному окну обрабатываться до тапов по маркерам позади него?

5 2

5 ответов:

Возможно, это не лучшее решение, оно кажется немного обратным, особенно с большим количеством маркеров, но оно должно работать.

, на ваш взгляд, карте делегат, создать свой делегат для:

-(BOOL)mapView:(GMSMapView *)mapView didTapMarker:(GMSMarker *)marker 
{
    for (int x = 0; x < myMapView.markers.count; x++) 
    { 
        GMSMarker * tempMarker = myMapView.markers[x]; 
        tempMarker.tappable = NO; 
    }
    mapView.selectedMarker = marker; 
    return YES; 
}

Тогда вам придется настроить другой метод делегирования:

- (void)mapView:(GMSMapView *)mapView didTapAtCoordinate:(CLLocationCoordinate2D)coordinate 
{
    for (int x = 0; x < myMapView.markers.count; x++) 
    { 
        GMSMarker * tempMarker = myMapView.markers[x]; 
        tempMarker.tappable = YES; 
    } 
}

Я настроил это так, что если пользователь нажмет за кадром, он закроет информационное окно и повторно включит "tappability" маркеров. Я знаю, что это не лучший способ, однако, похоже, учитывая вашу ситуацию, вы могли бы у меня нет выбора.

Мое предложение будет заключаться в том, что если у вас есть чрезмерное количество маркеров, которые также находятся вне экрана, возможно, вы можете установить его только для отключения экранных маркеров через свойство visible region (добавьте это в свой делегат маркера tapped)

-(BOOL)mapView:(GMSMapView *)mapView didTapMarker:(GMSMarker *)marker
{
    GMSVisibleRegion myVisibleRegion = mapView.projection.visibleRegion;
    GMSCoordinateBounds * currentBounds = [[GMSCoordinateBounds alloc]initWithRegion:myVisibleRegion];
    for (int x = 0; x < myMapView.markers.count; x++) {
        if ([currentBounds containsCoordinate:marker.position]) {
            GMSMarker * tempMarker = myMapView.markers[x];
            tempMarker.tappable = NO;
        }
    }
    return NO;
}

Тогда просто получите маркеры, которые находятся в этих границах.

Если вы это сделаете, в вашем делегате маркера tap задайте его как

- (void)mapView:(GMSMapView *)mapView didTapAtCoordinate:(CLLocationCoordinate2D)coordinate
{ 
    for (int x = 0; x < myMapView.markers.count; x++) {
        GMSMarker * tempMarker = myMapView.markers[x];
        if (tempMarker.tappable == NO) {
            tempMarker.tappable = YES;
        }
    }
}

Таким образом, он будет изменять только маркеры, которые в данный момент не являются привлекательная.

Надеюсь, это поможет!

На данный момент, я нашел это, чтобы быть лучшим обходным путем:

Https://github.com/ryanmaxwell/GoogleMapsCalloutView

В принципе, возвращение нулевого размера наследник UIView в -(наследник UIView*)положение:markerInfoWindow: так там не видно "Google карты" и "infowindow", и использовать возможность создавать и добавлять пользовательские наследник UIView на вершине положение одновременно. В mapView: didChangeCameraPosition UIView можно перемещать для отслеживания маркера по мере перемещения карты.

Edit: это также имеет то преимущество, что вы можете иметь реальные, интерактивные UIViews. (И SMCalloutView выглядит намного лучше, чем infoWindow по умолчанию в GoogleMaps SDK, тоже)

Для справки будущих читателей этой темы, эта проблема была решена в выпуске 1.4.0 в июле 2013 года. В примечаниях к выпуску, под списком разрешенных проблем, можно найти:

Информационные окна больше не позволяют кранам проходить через них

ЗДЕСЬ МОЖНО НАСТРОИТЬ ВЫБРАННОЕ ПОЛОЖЕНИЕ МАРКЕРА НА КАРТЕ, А ТАКЖЕ ОТКЛЮЧИТЬ МАРКЕРЫ ЗА ПОЛЬЗОВАТЕЛЬСКИМ ПРЕДСТАВЛЕНИЕМ. ЭТО НЕ ОДИН РАЗМЕР ПОДХОДИТ ДЛЯ ВСЕХ, И ВАМ НУЖНО БУДЕТ НАСТРОИТЬ ДЛЯ ВАШИХ СПЕЦИФИКАЦИЙ. ЛЮБЫЕ ДОПОЛНЕНИЯ ПРИВЕТСТВУЮТСЯ . . .

Наслаждайтесь!

Телец . . . Я не могу сказать вам точно, как это сделать для вашей ситуации; однако я могу дать вам свой код, чтобы посмотреть:

Во-первых, я настраиваю свою карту так, чтобы маркер располагался в более идеальном месте, чем центр . . .

(Важно отметить, что для этого требуется Северный пеленг, если вы позволите пользователям поворачивать карту, вам придется соответствующим образом настроить)

Вы можете хранить требования к регулировке в переменной и использовать те же самые, пока масштаб остается неизменным

- (void) adjustDisplayForImage: (GMSMarker *) marker
{
    // GET AN OFFSET AMOUNT IN DEGREES IN ORDER TO PROPERLY PLACE THE MARKER ACCORDING TO ZOOM

    CGPoint topLeft = CGPointMake(0, 0);
    CGRect screenRect = [[UIScreen mainScreen]bounds];
    CGPoint lowerLeft = CGPointMake(0, screenRect.size.height);

    CLLocationCoordinate2D topLeftCoordinate = [myMapView.projection coordinateForPoint:topLeft];
    CLLocationCoordinate2D lowerLeftCoordinate = [myMapView.projection coordinateForPoint:lowerLeft];

    CGFloat screenDistanceInDegreesLatitude = topLeftCoordinate.latitude - lowerLeftCoordinate.latitude;
    CGFloat adjustmentDistanceInDegreesLatitude = screenDistanceInDegreesLatitude / 2.8;
    // this is the amount that the new center needs to be offset in order to orient marker on screen

    // these are CLLocationDegrees variables, declared elsewhere
    adjustedLatitudeDegrees = marker.position.latitude + adjustmentDistanceInDegreesLatitude;

    adjustedLatitudeDegrees = marker.position.latitude + adjustmentDistanceInDegreesLatitude;

    CLLocationCoordinate2D newCenterCoordinate = CLLocationCoordinate2DMake(adjustedLatitudeDegrees, marker.position.longitude);

    myMapView.selectedMarker = marker;
    [myMapView animateToLocation:newCenterCoordinate];

    // I'm saving the current zoom so I don't have to get my adjustment distances again unless zoom changes
    lastZoom = myMapView.zoom;
}
Хорошо, теперь у меня есть эта информация, давайте уберем маркеры позади нашего вида . . .
- (void) disableMarkersBehindView
{
    // my marker window is 213 x 280

    int markerWindowHeight = 280;
    int markerWindowWidth = 213;
    int approximateMarkerHeight = 10;

    // I'm just guessing here for marker height, whatever your marker's height is, use that

    // because of my adjustment, the marker position is adjusted about down 35% from the middle

    CGFloat adjustedDistanceInCGPoints =  myMapView.frame.size.height * (1 / 2.7);

    // This is because the marker defaults to the middle of the screen
    CGFloat middleY = myMapView.frame.size.height / 2;
    CGFloat newMarkerPositionY = middleY + adjustedDistanceInCGPoints;

    CGFloat topOfMarkerWindowY = newMarkerPositionY - markerWindowHeight - approximateMarkerHeight;

    // now we need a NorthEast and a SouthWest coordinate

    // NORTHEAST

    CGFloat halfWidth = myMapView.frame.size.width / 2;
    CGFloat northEastX = halfWidth - (markerWindowWidth / 2);

    CGPoint northEastCGPoint = CGPointMake(northEastX, topOfMarkerWindowY);

    CLLocationCoordinate2D northEastCoordinate = [myMapView.projection coordinateForPoint:northEastCGPoint];

    // SOUTHWEST

    CGFloat southWestX = halfWidth + (markerWindowWidth / 2);
    CGPoint southWestCGPoint = CGPointMake(southWestX, newMarkerPositionY);

    CLLocationCoordinate2D southWestCoordinate = [myMapView.projection coordinateForPoint:southWestCGPoint];

    // Now, make a boundary

    GMSCoordinateBounds * myViewBounds = [[GMSCoordinateBounds alloc]initWithCoordinate: northEastCoordinate coordinate:southWestCoordinate];

    for (int x = 0 ; x < myMapView.markers.count ; x++) {

        GMSMarker * marker = myMapView.markers[x];
        if ([myViewBounds containsCoordinate:marker.position]) {
            marker.tappable = NO;
            // here maybe add the markers to a seperate array so you can quickly make them tappable again wherever you need to
        }
    }
}

Это учитывает различные уровни масштабирования, если вы ограничиваете масштабирование на вашей карте, вы, вероятно, могли бы упростить оно.

Не забудьте сделать ваши маркеры снова tappable, поэтому я предложил, возможно, сохранить их в отдельном массиве

И не забывайте, что регулировка основана только на Северном подшипнике, чтобы отключить вращающийся подшипник, используйте

myMapView.settings.rotateGestures = NO;

Если нет, то сначала переориентируйте карту на север или сделайте некоторые вычисления!

- надеюсь, это поможет!

Это, как я сделал. Установить положение.делегат = сам

Ваш .H file

#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>
#import <GoogleMaps/GoogleMaps.h>

@interface MapViewController : UIViewController <CLLocationManagerDelegate, GMSMapViewDelegate>

@end

ViewDidLoad of .m file

    - (void)viewDidLoad {
        [super viewDidLoad];

        GMSCameraPosition *camera = [GMSCameraPosition cameraWithLatitude:40.124291
                                                                longitude:-104.765625
                                                                     zoom:2];
        mapView_ = [GMSMapView mapWithFrame:CGRectZero camera:camera];
        mapView_.myLocationEnabled = YES;
        self.view = mapView_;
        mapView_.delegate = self;
    }

#pragma mark - set current location
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations{

}

#pragma mark - mapview events
-(BOOL) mapView:(GMSMapView *)mapView didTapMarker:(GMSMarker *)marker{
    NSLog(@"%@", marker.description);
//    show info window
    [mapView_ setSelectedMarker:marker];
    return YES;
}

-(void)mapView:(GMSMapView *)mapView didTapInfoWindowOfMarker:(GMSMarker *)marker{
    NSLog(@"info window tapped");
}