Actualmente estoy trabajando con el mapkit y estoy atascado.
Tengo una vista de anotación personalizada que estoy usando y quiero usar la propiedad de la imagen para mostrar el punto en el mapa con mi propio ícono. Tengo esto funcionando bien. Pero lo que también me gustaría hacer es anular la vista de llamada predeterminada (la burbuja que aparece con el título / subtítulo cuando se toca el icono de anotación). Quiero poder controlar la llamada en sí: el mapkit solo proporciona acceso a las vistas de llamada auxiliares izquierda y derecha, pero no hay forma de proporcionar una vista personalizada para la burbuja de llamada, o darle tamaño cero, o cualquier otra cosa.
Mi idea era anular selectAnnotation / deselectAnnotation en my MKMapViewDelegate
, y luego dibujar mi propia vista personalizada haciendo una llamada a mi vista de anotación personalizada. Esto funciona, pero solo cuando canShowCallout
está configurado YES
en mi clase de vista de anotación personalizada. Estos métodos NO se llaman si tengo esto configurado en NO
(que es lo que quiero, para que no se dibuje la burbuja de llamada predeterminada). Por lo tanto, no tengo forma de saber si el usuario tocó mi punto en el mapa (lo seleccionó) o tocó un punto que no es parte de mis vistas de anotaciones (lo eliminó) sin que aparezca la vista de burbuja de llamada predeterminada.
Intenté ir por un camino diferente y manejar todos los eventos táctiles yo mismo en el mapa, y parece que no puedo hacer que esto funcione. Leí otras publicaciones relacionadas con la captura de eventos táctiles en la vista del mapa, pero no son exactamente lo que quiero. ¿Hay alguna forma de profundizar en la vista del mapa para eliminar la burbuja de llamada antes de dibujar? Estoy perdido.
¿Alguna sugerencia? ¿Me estoy perdiendo algo obvio?
Respuestas:
Existe una solución aún más sencilla.
Cree un personalizado
UIView
(para su texto destacado).Luego cree una subclase de
MKAnnotationView
y anule de lasetSelected
siguiente manera:- (void)setSelected:(BOOL)selected animated:(BOOL)animated { [super setSelected:selected animated:animated]; if(selected) { //Add your custom view to self... } else { //Remove your custom view... } }
Boom, trabajo hecho.
fuente
detailCalloutAccessoryView
En los viejos tiempos esto era un fastidio, pero Apple lo ha resuelto, solo revisa los documentos en MKAnnotationView
view = MKPinAnnotationView(annotation: annotation, reuseIdentifier: identifier) view.canShowCallout = true view.detailCalloutAccessoryView = UIImageView(image: UIImage(named: "zebra"))
Realmente, eso es todo. Toma cualquier UIView.
fuente
Continuando con la brillante y simple respuesta de @ TappCandy, si desea animar su burbuja de la misma manera que la predeterminada, he producido este método de animación:
- (void)animateIn { float myBubbleWidth = 247; float myBubbleHeight = 59; calloutView.frame = CGRectMake(-myBubbleWidth*0.005+8, -myBubbleHeight*0.01-2, myBubbleWidth*0.01, myBubbleHeight*0.01); [self addSubview:calloutView]; [UIView animateWithDuration:0.12 delay:0.0 options:UIViewAnimationOptionCurveEaseOut animations:^(void) { calloutView.frame = CGRectMake(-myBubbleWidth*0.55+8, -myBubbleHeight*1.1-2, myBubbleWidth*1.1, myBubbleHeight*1.1); } completion:^(BOOL finished) { [UIView animateWithDuration:0.1 animations:^(void) { calloutView.frame = CGRectMake(-myBubbleWidth*0.475+8, -myBubbleHeight*0.95-2, myBubbleWidth*0.95, myBubbleHeight*0.95); } completion:^(BOOL finished) { [UIView animateWithDuration:0.075 animations:^(void) { calloutView.frame = CGRectMake(-round(myBubbleWidth/2-8), -myBubbleHeight-2, myBubbleWidth, myBubbleHeight); }]; }]; }]; }
Parece bastante complicado, pero siempre que la punta de su burbuja de llamada esté diseñada para estar en el centro de la parte inferior, debería poder reemplazarla
myBubbleWidth
y usarmyBubbleHeight
su propio tamaño para que funcione. Y recuerde asegurarse de que sus subvistas tengan suautoResizeMask
propiedad establecida en 63 (es decir, "todas") para que escalen correctamente en la animación.: -Joe
fuente
CABasicAnimation
... Sé que también tendría que animar la propiedad y, debido al desplazamiento del centro.CGRectMake
?Descubrí que esta es la mejor solución para mí. Tendrás que usar un poco de creatividad para hacer tus propias personalizaciones.
En su
MKAnnotationView
subclase, puede usar- (void)didAddSubview:(UIView *)subview{ int image = 0; int labelcount = 0; if ([[[subview class] description] isEqualToString:@"UICalloutView"]) { for (UIView *subsubView in subview.subviews) { if ([subsubView class] == [UIImageView class]) { UIImageView *imageView = ((UIImageView *)subsubView); switch (image) { case 0: [imageView setImage:[UIImage imageNamed:@"map_left"]]; break; case 1: [imageView setImage:[UIImage imageNamed:@"map_right"]]; break; case 3: [imageView setImage:[UIImage imageNamed:@"map_arrow"]]; break; default: [imageView setImage:[UIImage imageNamed:@"map_mid"]]; break; } image++; }else if ([subsubView class] == [UILabel class]) { UILabel *labelView = ((UILabel *)subsubView); switch (labelcount) { case 0: labelView.textColor = [UIColor blackColor]; break; case 1: labelView.textColor = [UIColor lightGrayColor]; break; default: break; } labelView.shadowOffset = CGSizeMake(0, 0); [labelView sizeToFit]; labelcount++; } } } }
Y si
subview
es unUICalloutView
, entonces puedes jugar con él y lo que hay dentro.fuente
if ([[[subview class] description] isEqualToString:@"UICalloutView"])
Creo que hay una forma mejor, pero funciona.Yo tuve el mismo problema. Hay una serie de publicaciones de blog sobre este tema en este blog http://spitzkoff.com/craig/?p=81 .
El solo uso de
MKMapViewDelegate
no te ayuda aquí y la subclasificaciónMKMapView
y el intento de extender la funcionalidad existente tampoco funcionó para mí.Lo que terminé haciendo es crear el mío propio
CustomCalloutView
que tengo encima del míoMKMapView
. Puede diseñar esta vista de la forma que desee.Mi
CustomCalloutView
tiene un método similar a este:- (void) openForAnnotation: (id)anAnnotation { self.annotation = anAnnotation; // remove from view [self removeFromSuperview]; titleLabel.text = self.annotation.title; [self updateSubviews]; [self updateSpeechBubble]; [self.mapView addSubview: self]; }
Toma un
MKAnnotation
objeto y establece su propio título, luego llama a otros dos métodos que son bastante feos que ajustan el ancho y el tamaño del contenido de la llamada y luego dibujan el bocadillo a su alrededor en la posición correcta.Finalmente, la vista se agrega como una subvista a mapView. El problema con esta solución es que es difícil mantener la llamada en la posición correcta cuando se desplaza la vista del mapa. Solo estoy ocultando la llamada en el método delegado de vistas de mapa en un cambio de región para resolver este problema.
Me tomó algún tiempo resolver todos esos problemas, pero ahora el anuncio casi se comporta como el oficial, pero lo tengo en mi propio estilo.
fuente
Básicamente, para resolver esto, es necesario: a) Evitar que aparezca la burbuja de llamada predeterminada. b) Averigüe en qué anotación se hizo clic.
Pude lograrlos: a) estableciendo canShowCallout en NO b) subclasificando, MKPinAnnotationView y anulando los métodos touchesBegan y touchesEnd.
Nota: debe manejar los eventos táctiles para MKAnnotationView y no MKMapView
fuente
Se me ocurrió un enfoque, la idea aquí es
// Detect the touch point of the AnnotationView ( i mean the red or green pin ) // Based on that draw a UIView and add it to subview. - (void)mapView:(MKMapView *)mapView regionWillChangeAnimated:(BOOL)animated { CGPoint newPoint = [self.mapView convertCoordinate:selectedCoordinate toPointToView:self.view]; // NSLog(@"regionWillChangeAnimated newPoint %f,%f",newPoint.x,newPoint.y); [testview setCenter:CGPointMake(newPoint.x+5,newPoint.y-((testview.frame.size.height/2)+35))]; [testview setHidden:YES]; } - (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated { CGPoint newPoint = [self.mapView convertCoordinate:selectedCoordinate toPointToView:self.view]; // NSLog(@"regionDidChangeAnimated newPoint %f,%f",newPoint.x,newPoint.y); [testview setCenter:CGPointMake(newPoint.x,newPoint.y-((testview.frame.size.height/2)+35))]; [testview setHidden:NO]; } - (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view { NSLog(@"Select"); showCallout = YES; CGPoint point = [self.mapView convertPoint:view.frame.origin fromView:view.superview]; [testview setHidden:NO]; [testview setCenter:CGPointMake(point.x+5,point.y-(testview.frame.size.height/2))]; selectedCoordinate = view.annotation.coordinate; [self animateIn]; } - (void)mapView:(MKMapView *)mapView didDeselectAnnotationView:(MKAnnotationView *)view { NSLog(@"deSelect"); if(!showCallout) { [testview setHidden:YES]; } }
Aquí, la vista de prueba tiene un
UIView
tamaño de 320x100, showCallout es BOOL,[self animateIn];
es la función que visualiza la animación comoUIAlertView
.fuente
Puede usar leftCalloutView, configurando annotation.text en @ ""
A continuación, encontrará el código de ejemplo:
pinView = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:defaultPinID]; if(pinView == nil){ pinView = [[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:defaultPinID] autorelease]; } CGSize sizeText = [annotation.title sizeWithFont:[UIFont fontWithName:@"HelveticaNeue" size:12] constrainedToSize:CGSizeMake(150, CGRectGetHeight(pinView.frame)) lineBreakMode:UILineBreakModeTailTruncation]; pinView.canShowCallout = YES; UILabel *lblTitolo = [[UILabel alloc] initWithFrame:CGRectMake(2,2,150,sizeText.height)]; lblTitolo.text = [NSString stringWithString:ann.title]; lblTitolo.font = [UIFont fontWithName:@"HelveticaNeue" size:12]; lblTitolo.lineBreakMode = UILineBreakModeTailTruncation; lblTitolo.numberOfLines = 0; pinView.leftCalloutAccessoryView = lblTitolo; [lblTitolo release]; annotation.title = @" ";
fuente
He sacado mi bifurcación del excelente SMCalloutView que resuelve el problema al proporcionar una vista personalizada para las llamadas y permitir anchos / alturas flexibles sin dolor. Aún quedan algunas peculiaridades por resolver, pero hasta ahora es bastante funcional:
https://github.com/u10int/calloutview
fuente