Domanda

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 proprio 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 sono stati creati tutti gli oggetti di annotazione in movimento 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.

È stato utile?

Soluzione

Ok, quindi per il 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ò assomiglia 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.

Altri suggerimenti

Sotto IOS 11 l'attuazione di displayPriority rotto tutte le soluzioni che utilizzano bringSubviewToFront o 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
        }
    }
}

Prova a zPosition configurazione vista annotazione del layer (annotationView.layer.zPosition) in:

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

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 aiuti

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 bringSubviewToFront e sendSubviewToBack, io uso insertSubview:aboveSubview e 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.

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

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 annotazione MKMapView usi non rispetta l'ordine aggiunto, o anche l'ordine di una proprietà annotations overriding. Quindi ...


Passi

• Creare un CADisplayLink
• Ogni fotogramma, riordinare le annotazioni utilizzando sia lo zPosition livello, e l'ordinamento della vista nella serie subviews del superview.
• Se viene selezionata la vista, promuoverlo verso la parte anteriore della tua ordinazione schema
• Toccando annotazioni rispetta ancora ordinazione MKMapView interno, nonostante le modifiche già effettuate. Per contrastare questo fenomeno, aggiungere un MKMapViewDelegate
• Nel metodo mapView:didSelect: dell'oggetto delegato, controllare 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 presa in considerazione
• Se l'annotazione selezionata è corretta, grande. In caso contrario, selezionare manualmente l'annotazione corretta utilizzando selectAnnotation: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.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top