Comment définir l'ordre de chevauchement MKAnnotationViews?

voix
29

J'ai plusieurs MKAnnotations (et leurs vues correspondantes) dans ma carte, et il a parfois vraiment bondé. Maintenant, les annotations dans mon application sont disponibles en deux saveurs: certains sont tenus de rester là où ils sont, tandis que d'autres se déplaceront au fil du temps. Je préfère avoir les plus stables visuellement en arrière-plan et les mobiles de passer toujours devant eux.

On pourrait penser, peut-être, que les annotations les plus récemment ajoutées à la carte finiraient à l'avant (ou bien tout au fond, au moins), mais cela ne semble pas être la règle. Pour autant que je peux dire, créer et ajouter toutes les annotations non mobiles d'abord, puis ajouter quelques nouvellement instanciés annotations en mouvement, mais beaucoup d'entre eux (mais pas tous!) Finissent par dessiné sous les perpétuellement immobile.

Fait intéressant, lorsque le temps passe, et encore de nouvelles annotations mobiles sont créés, ils ont tendance à graviter plus au sommet que les premiers - même si tous les objets d'annotation en mouvement ont été créés seulement après que les parties ont déjà été ajoutées immobiles à la carte.

Est-ce que quelqu'un sait un truc pour modifier cet étrange ordre naturel des vues d'annotation sur la carte? J'ai essayé de rechercher la carte API Kit, mais il ne semble pas parler d'une telle chose.

Créé 17/07/2009 à 20:33
source utilisateur
Dans d'autres langues...                            


7 réponses

voix
38

Ok, donc pour la méthode d'utilisation de la solution de MKMapViewDelegate


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

Dans cette méthode, vous devez réorganiser AnnotationView après avoir été ajouté à MapKit View. , Mai code ressemble tellement ceci:


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

}

Cela fonctionne pour moi.

Créé 31/07/2009 à 17:09
source utilisateur

voix
11

Essayez de zPosition de vue d'annotation de configuration couche (de annotationView.layer.zPosition) dans:

- (void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray *)views;
Créé 03/05/2013 à 11:40
source utilisateur

voix
4

Swift 3:

Je reçois l'emplacement des broches de l'API et j'avais des problèmes similaires, les broches qui devaient être sur le dessus ne sont pas. J'ai pu le résoudre comme ça.

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

}

J'espère que cela t'aides

Créé 05/12/2016 à 21:06
source utilisateur

voix
3

Sous iOS 11 la mise en œuvre de displayPriorityBroke toutes les solutions qui utilisent bringSubviewToFrontou zPosition.

Si vous substituez la vue CALayer de l'annotation, vous pouvez lutter contrôle de zPosition retour de l'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
        }
    }
}
Créé 25/01/2018 à 23:23
source utilisateur

voix
2

Je trouve que ce réordonner les vues d'annotation provoque la légende qui apparaît quand on est cliquée à ne plus être au - dessus de toutes les annotations. J'ai même essayé d' affiner de sorte qu'au lieu de bringSubviewToFrontet sendSubviewToBack, je l' utilise insertSubview:aboveSubviewet insertSubview:belowSubview:où le second argument est la première annotationView dans la liste. Cela semble causer beaucoup moins avant vers l' arrière diffusion, mais les sorties d'appel pop encore sous quelques annotations.

Créé 05/11/2009 à 15:21
source utilisateur

voix
1

Dans la fonction de délégué, vous pouvez sélectionner la broche pour le forcer au-dessus:

func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView?` {
    ...
    if my annotation is the special one {
        annotationView.isSelected = true
    }
    ...
}
Créé 18/02/2019 à 01:32
source utilisateur

voix
0

J'ai vraiment besoin de faire cela, et aucune des réponses (courant) semblait fournir une mise en œuvre fiable. Ils en quelque sorte travaillé, mais déplacement de la carte, en sélectionnant des annotations ou un zoom pourrait gâcher l'ordre nouveau.

La dernière solution bien comportés était pas si trivial, donc je vais juste esquisser les étapes de mon travail ici. L'ordre d'annotation qui MKMapViewutilise ne respecte pas l'ordre ajouté, ou même l'ordre d'une surchargée annotationspropriété. Alors...


Pas

• Créez CADisplayLink
• Chaque image, modifier l' ordre des annotations en utilisant à la fois la zPosition couche, et la commande de la vue du superview subviewsdu tableau.
• Si la vue est sélectionné, la promotion à l'avant dans votre système de commande
• En tapant sur les annotations respecte toujours interne MKMapViewcommande, malgré les modifications déjà apportées. Pour contrer cela, ajoutez un MKMapViewDelegate
• Dans le de l' objet délégué mapView:didSelect:de la méthode, vérifier si l'annotation sélectionnée est ce que vous souhaitez qu'il soit
• Vous pouvez trouver l'annotation correcte / priorité en exécutant des tests de succès sur les annotations vous, avec votre propre commande pris en compte
• Si l'annotation sélectionnée est correcte, grande. Sinon, sélectionnez manuellement l'annotation correcte à l' aideselectAnnotation:animated:


Et voila. La méthode ci-dessus semble bien fonctionner, et le succès de la performance de chaque exécution de ce cadre est pas trop mal. Vous pouvez aussi regarder le passage à MapBox, que je crois soutient ordre d'annotation, mais ce n'est pas toujours une option pour diverses raisons.

Créé 15/09/2017 à 01:54
source utilisateur

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