Come definire l'ordine di sovrapposizione MKAnnotationViews?

voti
29

Ho diversi MKAnnotations (ei loro punti di vista corrispondenti) in mia mappa, ed è a volte diventa molto affollata. Ora, le annotazioni nella mia app sono di due tipi: alcuni sono tenuti a rimanere dove sono, mentre altri si muoveranno col passare del tempo. Preferirei avere quelli più stabili visivamente sullo sfondo e quelli in movimento a passare sempre di fronte a loro.

Si potrebbe pensare, forse, che le annotazioni più recentemente aggiunti alla mappa finirebbe alla parte anteriore (o, in alternativa proprio in fondo, almeno), ma questo non sembra essere la regola. Per quanto posso dire, ho creare e aggiungere tutte le annotazioni non si muove prima, e quindi aggiungere alcune annotazioni in movimento neo-istanziati, ma molti di loro (anche se non tutti!) Finiscono disegnato sotto gli perennemente quelli impalato.

È interessante notare che, quando il tempo passa, e tuttavia vengono create nuove annotazioni in movimento, essi tendono a gravitare più verso l'alto rispetto ai primi - anche se tutti gli oggetti di annotazione in movimento sono stati creati solo dopo che le parti nonmoving erano già aggiunti alla mappa.

Qualcuno sa un trucco per alterare questo strano ordine naturale delle viste annotazione sulla mappa? Ho provato a cercare l'API Map Kit, ma non sembra parlare di una cosa del genere.

È pubblicato 17/07/2009 alle 20:33
fonte dall'utente
In altre lingue...                            


7 risposte

voti
38

Ok, quindi per metodo di soluzione utilizzo da MKMapViewDelegate


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

In questo metodo si dovrebbe riorganizzare AnnotationView dopo che è stato aggiunto al MapKit View. Quindi, codice può simile a questo:


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

}

Questo funziona per me.

Risposto il 31/07/2009 a 17:09
fonte dall'utente

voti
11

Cercate di zPosition configurazione vista annotazione del layer (annotationView.layer.zPosition) a:

- (void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray *)views;
Risposto il 03/05/2013 a 11:40
fonte dall'utente

voti
4

Swift 3:

Ottengo posizioni di contatti da API e ho avuto problemi simili, i perni che dovevano essere in cima non erano. Sono stato in grado di risolvere in questo modo.

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

}

Spero che questo ti aiuti

Risposto il 05/12/2016 a 21:06
fonte dall'utente

voti
3

Sotto IOS 11 l'attuazione displayPriorityrotto tutte le soluzioni che utilizzano bringSubviewToFronto zPosition.

Se si ignora CALayer della vista annotazione, si può lottare controllo della zPosition indietro dal sistema operativo.

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
        }
    }
}
Risposto il 25/01/2018 a 23:23
fonte dall'utente

voti
2

Ho constatato che questo riordino le viste di annotazione fa sì che il richiamo che si apre quando si fa clic di non essere più in cima a tutte le annotazioni. Ho anche provato raffinazione in modo che invece di bringSubviewToFronte sendSubviewToBack, io uso insertSubview:aboveSubviewe insertSubview:belowSubview:in cui il secondo argomento è la prima annotationView nella lista. Ciò sembrerebbe causare molto meno davanti a dietro dispersione, ma le uscite di chiamata ancora pop-up in alcune annotazioni.

Risposto il 05/11/2009 a 15:21
fonte dall'utente

voti
1

Nella funzione delegato, è possibile selezionare il pin per forzarlo in cima:

func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView?` {
    ...
    if my annotation is the special one {
        annotationView.isSelected = true
    }
    ...
}
Risposto il 18/02/2019 a 01:32
fonte dall'utente

voti
0

Ho davvero bisogno di fare questo, e nessuna delle risposte (correnti) sembrava di fornire un'implementazione affidabile. Essi sorta di lavorato, ma la panoramica della mappa, selezionare le annotazioni, o lo zoom potrebbe rovinare l'ordine di nuovo.

La soluzione finale, ben educati non era così banale, quindi mi limiterò a delineare i passi che ho fatto qui. L'ordinamento di annotazione che MKMapViewutilizza non rispetta l'ordine aggiunto, o anche l'ordine di un overriding annotationsproprietà. Così...


passi

• Creare un CADisplayLink
• Ogni telaio, riordinare annotazioni utilizzando sia lo zPosition strato, e l'ordinamento della vista nella del superview subviewsmatrice.
• Se viene selezionata la vista, promuoverlo al fronte nel vostro schema di ordinamento
• Toccando annotazioni rispetta ancora interno MKMapViewordinamento, nonostante le modifiche già effettuate. Per contrastare questo fenomeno, aggiungere un MKMapViewDelegate
• Nel dell'oggetto delegato mapView:didSelect:metodo, verificare se l'annotazione selezionato è quello che vuoi che sia
• Si può capire la correttezza delle annotazioni / priorità per l'esecuzione di test di successo sulle annotazioni da soli, con la vostra ordinazione prese in considerazione
• Se l'annotazione selezionata è corretta, grande. In caso contrario, selezionare manualmente l'annotazione corretta utilizzandoselectAnnotation:animated:


E il gioco è fatto. Il metodo sopra sembra funzionare bene, e il calo di prestazioni da eseguire questo ogni fotogramma non è male. Si potrebbe anche guardare il passaggio a MapBox, che credo supporta l'annotazione ordinazione, ma questo non è sempre un'opzione per vari motivi.

Risposto il 15/09/2017 a 01:54
fonte dall'utente

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more