Hvordan definere rekkefølgen på overlapp MKAnnotationViews?

stemmer
30

Jeg har flere MKAnnotations (og tilhørende visninger) i kartet mitt, og det noen ganger blir virkelig overfylt. Nå merknadene i min app kommer i to varianter: noen er nødt til å bo der de er, mens andre vil bevege seg som tiden går. Jeg foretrekker å ha de mer stabile de visuelt i bakgrunnen og bevegelige de å alltid gå foran dem.

En skulle tro, kanskje, at merknadene nylig lagt til kartet vil ende opp på forsiden (eller alternativt helt tilbake, i alle fall), men dette bare ikke ut til å være regelen. Så vidt jeg kan fortelle, jeg lage og legge alle de ikke-bevegelige merknader først, og deretter legge til noen nylig instantiated bevegelige merknader, men mange av dem (selv om ikke alle!) Ender opp med å trekkes under stadig bom stille seg.

Interessant, når tiden går, og likevel nye bevegelige merknader er opprettet, har de en tendens til å bevege mer til toppen enn de første - selv om alle bevegelige merknads gjenstander ble skapt først etter at nonmoving deler ble allerede lagt til kartet.

Vet noen et triks for å endre denne merkelige naturlige rekkefølgen av merknads synspunkter på kartet? Jeg prøvde å søke i kart Kit API, men det ser ikke ut til å snakke om noe slikt.

Publisert på 17/07/2009 klokken 19:33
kilden bruker
På andre språk...                            


7 svar

stemmer
39

OK, så for oppløsning bruke metoden fra MKMapViewDelegate


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

I denne metoden bør du ordne AnnotationView etter at det ble lagt inn i mapKit View. Så kode mai ser slik ut:


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

}

Dette fungerer for meg.

Svarte 31/07/2009 kl. 16:09
kilden bruker

stemmer
11

Prøv å sette opp merknaden visning lagets zPosition (annotationView.layer.zPosition) i:

- (void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray *)views;
Svarte 03/05/2013 kl. 10:40
kilden bruker

stemmer
6

Under iOS 11 gjennomføring av displayPrioritybrøt alle løsninger som bruker bringSubviewToFronteller zPosition.

Hvis du overstyre merknaden visningens CALayer, kan du kjempe kontroll over zPosition tilbake fra 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
        }
    }
}
Svarte 25/01/2018 kl. 23:23
kilden bruker

stemmer
4

Swift 3:

Jeg får pin steder fra API og jeg hadde lignende problemer, pinnene som måtte være på toppen var det ikke. Jeg var i stand til å løse det på denne måten.

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

}

Håper dette hjelper

Svarte 05/12/2016 kl. 21:06
kilden bruker

stemmer
2

Jeg synes at dette etterbestilling synspunktene merknads fører til at bildeforklaringen som dukker opp når man klikker på å ikke lenger være på toppen av alle merknadene. Jeg har selv prøvd å avgrense det slik at i stedet for bringSubviewToFrontog sendSubviewToBack, jeg bruker insertSubview:aboveSubviewog insertSubview:belowSubview:hvor det andre argumentet er den første annotationView i listen. Dette synes å føre til mye mindre foran til bak spredning, men samtalen outs fortsatt dukke opp under noen merknader.

Svarte 05/11/2009 kl. 14:21
kilden bruker

stemmer
1

I representanten funksjonen, kan du velge pin for å tvinge den på toppen:

func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView?` {
    ...
    if my annotation is the special one {
        annotationView.isSelected = true
    }
    ...
}
Svarte 18/02/2019 kl. 01:32
kilden bruker

stemmer
0

Jeg virkelig trengte å gjøre dette, og ingen av de (nåværende) svar syntes å gi en pålitelig gjennomføring. De slags arbeidet, men panorering kartet, velge merknader, eller zoomer inn kan rote opp bestillingen på nytt.

Den endelige, veloppdragen løsning var ikke så trivielt, så jeg skal bare skissere fremgangsmåten jeg tok her. Den annotering bestilling som MKMapViewbenytter ikke respekterer den tilsatte orden, eller til og med i størrelsesorden av en overstyrt annotationsegenskap. Så...


Steps

• Lag en CADisplayLink
• Hver ramme, omorganisere merknader bruke begge lag zPosition, og utsikten er bestilling i Super er subviewsarray.
• Hvis visningen er valgt, fremme det til fronten i din bestilling ordningen
• Tapping på merknader fortsatt respekterer intern MKMapViewbestilling, til tross for de allerede gjort endringer. For å motvirke dette, legger en MKMapViewDelegate
• I representanten objektets mapView:didSelect:metode, sjekk om den valgte merknaden er det du vil at det skal være
• Du kan regne ut riktig / prioritert merknad ved å kjøre hit tester på kommentarer selv, med din egen bestilling tatt hensyn
• Hvis den valgte merknaden er riktig, stor. Hvis ikke, må du manuelt velge riktig merknaden hjelpselectAnnotation:animated:


Og det du har det. Ovennevnte metode synes å fungere godt, og ytelse hit fra å kjøre dette hver ramme er ikke så ille. Du kan også se på å bytte til MapBox, som jeg mener støtter merknaden bestilling, men dette er ikke alltid et alternativ for ulike grunner.

Svarte 15/09/2017 kl. 01:54
kilden bruker

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