¿Cómo se define el orden de superposición de MKAnnotationViews?

votos
29

Tengo varias MKAnnotaciones (y sus vistas correspondientes) en mi mapa, y a veces se llena de gente. Ahora, las anotaciones en mi aplicación vienen en dos formas: algunas están destinadas a permanecer donde están, mientras que otras se moverán con el paso del tiempo. Prefiero tener los más estables visualmente en el fondo y los más móviles para pasar siempre delante de ellos.

Uno pensaría, tal vez, que las anotaciones agregadas más recientemente al mapa terminarían en la parte frontal (o alternativamente en la parte trasera, al menos) pero esto simplemente no parece ser la regla. Por lo que puedo decir, creo y agrego TODAS las anotaciones que no se mueven primero, y luego agrego algunas anotaciones en movimiento recién creadas, pero muchas de ellas (¡aunque no todas!) Terminan dibujadas debajo de las que permanecen en stock perpetuamente.

Curiosamente, cuando pasa el tiempo y se crean nuevas anotaciones en movimiento, tienden a gravitar más hacia la parte superior que las primeras, incluso si todos los objetos de anotación en movimiento se crearon solo después de que las partes no movidas ya se agregaron al mapa.

¿Alguien sabe un truco para alterar este extraño orden natural de las vistas de anotación en el mapa? Traté de buscar la API de Map Kit, pero no parece hablar de tal cosa.

Publicado el 17/07/2009 a las 20:33
fuente por usuario
En otros idiomas...                            


7 respuestas

votos
38

Ok, entonces para el método de uso de solución de MKMapViewDelegate


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

En este método, debe reorganizar AnnotationView después de que se haya agregado a mapKit View. Entonces, el código puede verse así:


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

}

Esto funciona para mí

Respondida el 31/07/2009 a las 17:09
fuente por usuario

votos
11

Trate de zPosition configuración de vista de anotación de capa (annotationView.layer.zPosition) en:

- (void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray *)views;
Respondida el 03/05/2013 a las 11:40
fuente por usuario

votos
4

Swift 3:

Consigo localización de los pines de la API y que estaba teniendo problemas similares, los pasadores que tenían que estar en la cima no lo eran. Yo era capaz de resolverlo como este.

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

}

Espero que esto ayude

Respondida el 05/12/2016 a las 18:06
fuente por usuario

votos
3

Bajo el IOS 11 la aplicación del displayPriorityrompió todas las soluciones que utilizan bringSubviewToFronto zPosition.

Si anula CALayer de la vista de anotación, se puede luchar el control de zPosition vuelta desde el 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
        }
    }
}
Respondida el 25/01/2018 a las 20:23
fuente por usuario

votos
2

Me parece que este reordenamiento de las vistas de anotación causa que la llamada emergente que aparece cuando se hace clic en una de ellas deje de estar en la parte superior de todas las anotaciones. Incluso intenté refinarlo para que en vez de bringSubviewToFronty sendSubviewToBack, yo use insertSubview:aboveSubviewy insertSubview:belowSubview:donde el segundo argumento sea la primera AnotaciónVer en la lista. Esto parecería causar mucho menos dispersión frontal a posterior, pero las llamadas salientes aún aparecen debajo de algunas anotaciones.

Respondida el 05/11/2009 a las 15:21
fuente por usuario

votos
1

En la función de delegado, puede seleccionar el pasador a la fuerza en la parte superior:

func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView?` {
    ...
    if my annotation is the special one {
        annotationView.isSelected = true
    }
    ...
}
Respondida el 18/02/2019 a las 01:32
fuente por usuario

votos
0

Que realmente se necesita para hacer esto, y ninguna de las respuestas (actuales) parecía proporcionar una implementación fiable. Ellos tipo de trabajado, pero la exploración del mapa, la selección de anotaciones, o hacer zoom podría estropear el orden de nuevo.

La solución final, de buen comportamiento no era tan trivial, así que voy a esbozar los pasos que di aquí. El ordenamiento anotación que MKMapViewutiliza no respeta el orden añadido, o incluso el orden de un overriden annotationspropiedad. Asi que...


Pasos

• Crear un CADisplayLink
• Cada cuadro, cambiar el orden de las anotaciones utilizando tanto la capa de zPosition, y el pedido de la vista en el supervista subviewsmatriz.
• Si se selecciona la vista, promoverlo al frente en su esquema de ordenamiento
• Al tocar en anotaciones sigue respetando interna MKMapViewde pedidos, a pesar de los cambios ya realizados. Para contrarrestar esto, agregar un MKMapViewDelegate
• En el objeto delegado mapView:didSelect:método, comprobar si la anotación seleccionada es lo que le gustaría que fuera
• Puede averiguar la anotación correcta / priorizados por la ejecución de pruebas de golpe en las anotaciones usted mismo, con su propio ordenamiento tenido en cuenta
• Si la anotación seleccionada es correcta, muy bien. Si no es así, seleccionar manualmente la anotación correcta utilizandoselectAnnotation:animated:


Y ahí lo tienes. El método anterior parece funcionar bien, y el impacto en el rendimiento de la ejecución de este cada cuadro no es tan malo. También podría mirar a cambiar a MapBox, que creo que es compatible con la anotación de pedidos, pero esto no es siempre una opción por varias razones.

Respondida el 14/09/2017 a las 22:54
fuente por usuario

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