Pergunta

Eu tenho várias MKAnnotations (e suas vistas correspondentes) em meu mapa, e, por vezes, fica muito lotado. Agora, as anotações no meu aplicativo vêm em dois sabores: alguns são obrigados a permanecer onde estão, enquanto outros se moverá conforme o tempo passa. Eu prefiro ter os mais estáveis ??visualmente em segundo plano e os que se deslocam para sempre passar na frente deles.

Alguém poderia pensar que, talvez, que as anotações adicionadas mais recentemente ao mapa acabaria para a frente (ou, alternativamente, bem no fundo, pelo menos), mas isso simplesmente não parece ser a regra. Tanto quanto eu posso dizer, eu criar e adicionar todas as anotações não se mover primeiro, e depois adicionar algumas anotações móveis recém-instanciado, mas muitos deles (embora não todos!) Acabam desenhado sob os perpetuamente completamente imóvel.

Curiosamente, quando o tempo passa, e ainda novas anotações móveis são criados, eles tendem a gravitar mais para a parte superior do que os primeiros - mesmo se todos os objetos de anotação em movimento foram criados somente após as partes nonmoving já foram adicionadas ao mapa .

Alguém sabe um truque para alterar esta ordem natural estranha das vistas de anotação no mapa? Tentei pesquisar na API Mapa Kit, mas não parecem falar de tal coisa.

Foi útil?

Solução

Ok, então para o método de utilização da solução MKMapViewDelegate


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

Neste método, você deve reorganizar AnnotationView depois de ter sido adicionado ao MapKit View. Então, código pode esta aparência:


- (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];
      }
   }

}

Isso funciona para mim.

Outras dicas

De acordo com iOS 11 a implementação de displayPriority quebrou todas as soluções que usam bringSubviewToFront ou zPosition.

Se você substituir CALayer da vista de anotação, você pode lutar o controle de zPosition volta do OS.

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

Tente zPosition configuração vista de anotação da camada (annotationView.layer.zPosition) em:

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

Swift 3:

Eu recebo locais dos pinos de API e eu estava tendo problemas semelhantes, os pinos que tinham que estar no topo não eram. Eu era capaz de resolvê-lo assim.

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. 
    }

}

Espero que isso ajude

Eu estou achando que esta reordenação das vistas de anotação faz com que o texto explicativo que aparece quando um é clicado para não estar no topo de todas as anotações. Eu até tentei refiná-lo de modo que em vez de bringSubviewToFront e sendSubviewToBack, eu uso insertSubview:aboveSubview e insertSubview:belowSubview: onde o segundo argumento é o primeiro annotationView na lista. Isto parece causar muito menos frente para trás dispersão, mas as saídas de chamada ainda aparecer em algumas anotações.

Na função de delegado, você pode selecionar o pino para forçá-lo no topo:

func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView?` {
    ...
    if my annotation is the special one {
        annotationView.isSelected = true
    }
    ...
}

Eu realmente precisava fazer isso, e nenhuma das respostas (correntes) parecia fornecer uma implementação confiável. Eles tipo de funcionou, mas percorre o mapa, a seleção de anotações, ou zoom in poderia atrapalhar a ordem novamente.

A solução final, bem comportado não era tão trivial, por isso vou apenas delinear os passos que tomou aqui. A anotação ordenando que os usos MKMapView não respeita a ordem adicionado, ou mesmo o fim de uma propriedade annotations anulado. Então ...


Passos

• Criar uma CADisplayLink
• Cada quadro, anotações de reordenamento usando ambos o zPosition camada, e ordenação da vista em ordem subviews do superview.
• Se a vista for selecionado, promovê-lo para a frente em seu esquema de ordenação
• Tocar em anotações ainda respeita ordenação MKMapView interna, apesar das alterações já introduzidas. Para contrariar esta situação, adicione um MKMapViewDelegate
• No método mapView:didSelect: do objeto delegado, cheque se a anotação selecionada é o que você gostaria que fosse
• Você pode descobrir a anotação correta / priorizados pela execução de testes de sucesso nas anotações mesmo, com seu próprio ordenamento tidos em conta
• Se a anotação selecionada está correta, ótimo. Se não, seleccionar manualmente a anotação correta usando selectAnnotation:animated:


E aí está. O método acima parece funcionar bem, e o impacto no desempenho de executar este cada quadro não é tão ruim. Você também pode olhar para a mudança para MapBox, que eu acredito suportes anotação de pedidos, mas isso nem sempre é uma opção para várias razões.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top