Как определить порядок наложения MKAnnotationViews? - PullRequest
36 голосов
/ 17 июля 2009

У меня есть несколько примечаний MKA (и соответствующих им видов) на моей карте, и иногда они действительно переполнены. Теперь аннотации в моем приложении представлены в двух вариантах: некоторые будут оставаться на своих местах, а другие будут двигаться с течением времени. Я бы предпочел иметь более устойчивые визуально на заднем плане и движущиеся, чтобы они всегда проходили перед ними.

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

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

Кто-нибудь знает хитрость, чтобы изменить этот странный естественный порядок аннотаций на карте? Я попытался выполнить поиск в Map Kit API, но, похоже, об этом ничего не говорится.

Ответы [ 7 ]

41 голосов
/ 31 июля 2009

Хорошо, поэтому для решения используйте метод из MKMapViewDelegate


- (void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray *)views
 

В этом методе вы должны изменить порядок AnnotationView после его добавления в mapKit View. Итак, код может выглядеть так:


- (void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray *)views {
   for (MKAnnotationView * annView in views) {
      TopBottomAnnotation * ann = (TopBottomAnnotation *) [annView annotation];
      if ([ann top]) {
         [[annView superview] bringSubviewToFront:annView];
      } else {
         [[annView superview] sendSubviewToBack:annView];
      }
   }

}

Это работает для меня.

12 голосов
/ 26 января 2018

Под iOS 11 реализация displayPriority сломала все решения, использующие bringSubviewToFront или zPosition.

Если вы переопределите CALayer представления аннотаций, вы можете восстановить управление zPosition из ОС.

class AnnotationView: MKAnnotationView {

    /// Override the layer factory for this class to return a custom CALayer class
    override class var layerClass: AnyClass {
        return ZPositionableLayer.self
    }

    /// convenience accessor for setting zPosition
    var stickyZPosition: CGFloat {
        get {
            return (self.layer as! ZPositionableLayer).stickyZPosition
        }
        set {
            (self.layer as! ZPositionableLayer).stickyZPosition = newValue
        }
    }

    /// force the pin to the front of the z-ordering in the map view
   func bringViewToFront() {
        superview?.bringSubview(toFront: self)
        stickyZPosition = CGFloat(1)
    }

    /// force the pin to the back of the z-ordering in the map view
   func setViewToDefaultZOrder() {
        stickyZPosition = CGFloat(0)
    }

}

/// iOS 11 automagically manages the CALayer zPosition, which breaks manual z-ordering.
/// This subclass just throws away any values which the OS sets for zPosition, and provides
/// a specialized accessor for setting the zPosition
private class ZPositionableLayer: CALayer {

    /// no-op accessor for setting the zPosition
    override var zPosition: CGFloat {
        get {
            return super.zPosition
        }
        set {
            // do nothing
        }
    }

    /// specialized accessor for setting the zPosition
    var stickyZPosition: CGFloat {
        get {
            return super.zPosition
        }
        set {
            super.zPosition = newValue
        }
    }
}
11 голосов
/ 03 мая 2013

Попробуйте установить zPosition слоя представления аннотации (annotationView.layer.zPosition) в:

- (void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray *)views;
4 голосов
/ 06 декабря 2016

Свифт 3:

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

var count = 0 // just so we don't get the same index in bottom pins
func mapView(_ mapView: MKMapView, didAdd views: [MKAnnotationView]) {  
    for view in views {
        view.layer.zPosition = CGFloat(count)
    }
    count += 1
    if count > 500 {
        count = 250 // just so we don't end up with 999999999999+ as a value for count, plus I have at least 30 pins that show at the same time and need to have lower Z-Index values than the top pins. 
    }

}

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

2 голосов
/ 18 февраля 2019

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

func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView?` {
    ...
    if my annotation is the special one {
        annotationView.isSelected = true
    }
    ...
}
2 голосов
/ 05 ноября 2009

Я обнаружил, что переупорядочивание представлений аннотаций вызывает сноску, которая появляется при нажатии, чтобы больше не находиться над всеми аннотациями. Я даже попытался уточнить его, чтобы вместо bringSubviewToFront и sendSubviewToBack я использовал insertSubview:aboveSubview и insertSubview:belowSubview:, где вторым аргументом является первый вид аннотации в списке. Казалось бы, это может привести к гораздо меньшему рассеянию спереди назад, но вызовы по-прежнему появляются под некоторыми аннотациями.

0 голосов
/ 15 сентября 2017

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

Окончательное, хорошо себя зарекомендовавшее решение не было таким тривиальным, поэтому я просто обрисую шаги, которые я предпринял здесь. Порядок аннотаций, используемый MKMapView, не учитывает добавленный порядок или даже порядок переопределенного свойства annotations. Итак ...


Steps

• Создать CADisplayLink
• Каждый кадр, переупорядочивать аннотации, используя и слой zPosition, и порядок представления в массиве subviews суперпредставления.
• Если выбран вид, выдвиньте его на передний план в схеме заказа
• Нажатие на аннотации по-прежнему учитывает внутреннее упорядочение MKMapView, несмотря на уже внесенные изменения. Чтобы противостоять этому, добавьте MKMapViewDelegate
• В методе mapView:didSelect: объекта делегата проверьте, соответствует ли выбранная аннотация желаемому
• Вы можете определить правильную / расставленную по приоритетам аннотацию, запустив тесты попадания на аннотации самостоятельно, с учетом собственного заказа
• Если выбранная аннотация верна, отлично. Если нет, выберите правильную аннотацию вручную, используя selectAnnotation:animated:


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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...