Wie die Reihenfolge der überlappende MKAnnotationViews definieren?

stimmen
29

Ich habe mehrere MKAnnotations (und ihre entsprechenden Ansichten) in meiner Karte, und es wird manchmal wirklich überfüllt. Nun kommen die Anmerkungen in meiner app in zwei Geschmacksrichtungen: einige sind verpflichtet, zu bleiben, wo sie sind, während andere bewegen, wie die Zeit vergeht. Ich würde es vorziehen, die mehr stabilsten optisch in den Hintergrund und die beweglichen diejenigen zu haben, immer vor passieren von ihnen.

Man würde denkt vielleicht, dass die Anmerkungen zuletzt die Karte hinzugefügt würden bis zu dem vorderen Ende (oder alternativ an den hintersten, zumindest), aber dies scheint nicht nur die Regel zu sein. Soweit ich sagen kann, ich schaffen und werden zuerst die unbewegten Anmerkungen hinzufügen und dann einige neu instanziiert bewegenden Anmerkungen hinzufügen, aber viele von ihnen (wenn auch nicht alle!) Unter den ständig Aktien noch diejenigen erstellt beenden.

Interessanterweise, wenn die Zeit vergeht, und noch neue Bewegungs Anmerkungen erstellt werden, neigen sie dazu, mehr an die Spitze gravitieren als die ersten, die - auch wenn alle beweglichen Annotation Objekte nur erstellt wurden, nachdem die unbewegliche Teile bereits auf der Karte hinzugefügt wurden.

Kennt jemand einen Trick diese seltsame natürliche Reihenfolge der Beschriftungsansichten auf der Karte zu verändern? Ich versuchte, die Map Kit API zu suchen, aber es scheint nicht so etwas zu sprechen.

Veröffentlicht am 17/07/2009 um 20:33
quelle vom benutzer
In anderen Sprachen...                            


7 antworten

stimmen
38

Ok, so Lösungs Verwendung von Verfahren MKMapViewDelegate


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

Bei dieser Methode sollten Sie AnnotationView neu ordnen, nachdem es zu MapKit Ansicht hinzugefügt wurde. So sieht Code kann wie folgt aus:


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

}

Dies funktioniert für mich.

Beantwortet am 31/07/2009 um 17:09
quelle vom benutzer

stimmen
11

Versuchen Sie, Setup-Anmerkungsansicht Layers zPosition (annotationView.layer.zPosition) in:

- (void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray *)views;
Beantwortet am 03/05/2013 um 11:40
quelle vom benutzer

stimmen
4

Swift 3:

Ich Nadelstellen von API bekommen und ich habe ähnliche Probleme, die Stifte, die an der Spitze zu sein hatten, waren nicht. Ich konnte es so lösen.

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

}

Hoffe das hilft

Beantwortet am 05/12/2016 um 21:06
quelle vom benutzer

stimmen
3

Unter iOS 11 die Umsetzung displayPrioritybrach alle Lösungen , die verwenden bringSubviewToFrontoder zPosition.

Wenn Sie die Anmerkungsansicht des CALayer überschreiben, können Sie die Kontrolle über zPosition zurück aus dem O ringen.

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
        }
    }
}
Beantwortet am 25/01/2018 um 23:23
quelle vom benutzer

stimmen
2

Ich finde , dass dies die Beschriftungsansichten Neuordnungs bewirkt , dass der callout, das erscheint , wenn man angeklickt wird nicht mehr sein , oben auf allen Anmerkungen. Ich habe sogar versucht , es so , dass anstelle der Verfeinerung bringSubviewToFrontund sendSubviewToBackverwende ich insertSubview:aboveSubviewund insertSubview:belowSubview:wo das zweite Argument ist die erste AnnotationView in der Liste. Dies scheint viel weniger vorne zu verursachen Streuung zu unterstützen , aber die Anfahrten Pop noch unter einigen Anmerkungen auf.

Beantwortet am 05/11/2009 um 15:21
quelle vom benutzer

stimmen
1

In der Delegierten-Funktion können Sie den Stift auswählen, um es auf Kraft:

func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView?` {
    ...
    if my annotation is the special one {
        annotationView.isSelected = true
    }
    ...
}
Beantwortet am 18/02/2019 um 01:32
quelle vom benutzer

stimmen
0

Ich wirklich brauchte, dies zu tun, und keiner der (aktuellen) Antworten schien eine zuverlässige Umsetzung. Sie arbeiteten Art, aber die Karte Panning, die Auswahl Anmerkungen oder Zoomen konnte wieder die Reihenfolge durcheinander bringen.

Die letzte, gut erzogene Lösung war nicht so trivial, so dass ich nur die Maßnahmen erläutert , die ich hier bin. Die Anmerkung der Bestellung , dass MKMapViewdie hinzugefügte Ordnung nicht respektiert verwendet, oder auch die Reihenfolge einer überschriebenen annotationsEigenschaft. Damit...


Schritte

• Erstellen einer CADisplayLink
• Jeder Rahmen, neu anordnen Annotationen verwenden sowohl die Schicht zPosition und die Reihenfolge der Ansicht in der die Superview- subviewsArray.
• Wenn die Ansicht ausgewählt wird, fördern sie in Ihrem Ordnungsschema nach vorne
• noch auf Anmerkungen Tapping interne respektiert MKMapViewBestellung, trotz der bereits vorgenommenen Änderungen. Um dem entgegenzuwirken, ein hinzufügen MKMapViewDelegate
• Im Delegatobjekt der mapView:didSelect:Methode überprüfen , ob die gewählte Anmerkung ist , was Sie es sein möchten
• Sie herausfinden können , die richtige / priorisiert Anmerkung selbst auf den Anmerkungen Treffertests ausgeführt wird , mit Ihrem eigenen Bestell berücksichtigen in
• Wenn die gewählte Anmerkung richtig ist , groß. Wenn nicht, wählen Sie manuell die richtige Anmerkung mitselectAnnotation:animated:


Und dort haben Sie es. Das oben beschriebene Verfahren scheint gut zu funktionieren, und die Leistungseinbußen diesen jeden Frame von Laufen ist nicht so schlimm. Sie könnten auch einen Blick auf MapBox beim Einschalten, die ich unterstützt Anmerkung Bestellung glauben, aber dies ist nicht immer eine Option aus verschiedenen Gründen.

Beantwortet am 15/09/2017 um 01:54
quelle vom benutzer

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