¿Cómo mostrar 2 líneas de texto para subtítulos de MKAnnotación y cambiar la imagen para el botón de la derecha?

Estoy mirando el ejemplo de MapCallout de Apple para anotaciones y leyendas de mapas (== burbujas que aparecen cuando haces clic en un pin). Cada anotación allí tiene coordenadas, título y subtítulo. Me gustaría mostrar los subtítulos en 2 líneas, intenté con:

- (NSString *)subtitle { return @"Founded: June 29, 1776\nSecond line text"; } 

pero el texto “Segunda línea de texto” se mantiene en una línea y hace que la burbuja se amplíe. Obtengo esto:

enter image description here

También me gustaría cambiar la imagen del botón a una de las mías, el código que establece el botón es actualmente así:

 UIButton* rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure]; 

¿Algunas ideas?

EDITAR: Probé el consejo de 7KV7. El cambio de botón es exitoso, pero aún no puedo obtener subtítulos en 2 líneas. Mi código:

 MKPinAnnotationView* customPinView = [[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:BridgeAnnotationIdentifier] autorelease]; customPinView.pinColor = MKPinAnnotationColorPurple; customPinView.animatesDrop = YES; // Button UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom]; button.frame = CGRectMake(0, 0, 23, 23); button.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter; button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter; //UIEdgeInsets titleInsets = UIEdgeInsetsMake(7.0, -20.0, 7.0, 7.0); //button.titleEdgeInsets = titleInsets; [button setImage:[UIImage imageNamed:@"ic_phone_default.png"] forState:UIControlStateNormal]; //[button setImage:[UIImage imageNamed:@"ic_phone_selected.png"] forState:UIControlStateSelected]; [button setImage:[UIImage imageNamed:@"ic_phone_selected.png"] forState:UIControlStateHighlighted]; [button addTarget:self action:@selector(showDetails:) forControlEvents:UIControlEventTouchUpInside]; customPinView.rightCalloutAccessoryView = button; //two labels UIView *leftCAV = [[UIView alloc] initWithFrame:CGRectMake(0,0,50,50)]; //[leftCAV addSubview : button]; UILabel *l1=[[UILabel alloc] init]; l1.frame=CGRectMake(0, 15, 50, 50); l1.text=@"First line of subtitle"; l1.font=[UIFont fontWithName:@"Arial Rounded MT Bold" size:(10.0)]; UILabel *l2=[[UILabel alloc] init]; l2.frame=CGRectMake(0, 30, 50, 50); l2.text=@"Second line of subtitle"; l2.font=[UIFont fontWithName:@"Arial Rounded MT Bold" size:(10.0)]; [leftCAV addSubview : l1]; [leftCAV addSubview : l2]; customPinView.leftCalloutAccessoryView = leftCAV; //customPinView. customPinView.canShowCallout = YES; return customPinView; 

Entiendo esto:

enter image description here

 - (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id )annotation { MKAnnotationView *annotationView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:@"loc"]; // Button UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom]; button.frame = CGRectMake(0, 0, 23, 23); button.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter; button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter; [button setImage:[UIImage imageNamed:yourImageName] forState:UIControlStateNormal]; [advertButton addTarget:self action:@selector(buttonPress:) forControlEvents:UIControlEventTouchUpInside]; annView.rightCalloutAccessoryView = button; // Image and two labels UIView *leftCAV = [[UIView alloc] initWithFrame:CGRectMake(0,0,23,23)]; [leftCAV addSubview : yourImageView]; [leftCAV addSubview : yourFirstLabel]; [leftCAV addSubview : yourSecondLabel]; annotationView.leftCalloutAccessoryView = leftCAV; annotationView.canShowCallout = YES; return pin; } 

ACTUALIZAR

El estilo predeterminado para las anotaciones solo admite el título y los subtítulos. Ni el título ni el subtítulo pueden incluir saltos de línea. No puedes hacer esto sin crear subclases.

Para usar una vista personalizada, revise el código de muestra de Apple:

http://developer.apple.com/library/ios/#samplecode/WeatherMap/Introduction/Intro.html

También creo que hay un problema en tu código

 UILabel *l1=[[UILabel alloc] init]; l1.frame=CGRectMake(0, 15, 50, 50); l1.text=@"First line of subtitle"; l1.font=[UIFont fontWithName:@"Arial Rounded MT Bold" size:(10.0)]; UILabel *l2=[[UILabel alloc] init]; l2.frame=CGRectMake(0, 30, 50, 50); l2.text=@"Second line of subtitle"; l2.font=[UIFont fontWithName:@"Arial Rounded MT Bold" size:(10.0)]; [leftCAV addSubview : l1]; [leftCAV addSubview : l2]; 

l1 tiene un marco (0, 15, 50, 50) y l2 tiene (0, 30, 50, 50). ¿No se superponen estas dos? Quiero decir que l1 comenzará desde y = 15 y su altura es 50. Entonces, cuando l2 comienza desde 30, puede superponerse … ¿Pueden verificarlo cambiando los marcos?

Por favor use esto

  - (MKAnnotationView *) mapView:(MKMapView *)mapView viewForAnnotation:(id)annotation { if ([annotation isKindOfClass:[MKUserLocation class]]) return nil; if ([annotation isKindOfClass:[CustomAnnotation class]]) { CustomAnnotation *customAnnotation = (CustomAnnotation *) annotation; MKAnnotationView *annotationView = [mapView dequeueReusableAnnotationViewWithIdentifier:@"CustomAnnotation"]; if (annotationView == nil) annotationView = customAnnotation.annotationView; else annotationView.annotation = annotation; //Adding multiline subtitle code UILabel *subTitlelbl = [[UILabel alloc]init]; subTitlelbl.text = @"sri ganganagar this is my home twon.sri ganganagar this is my home twon.sri ganganagar this is my home twon. "; annotationView.detailCalloutAccessoryView = subTitlelbl; NSLayoutConstraint *width = [NSLayoutConstraint constraintWithItem:subTitlelbl attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationLessThanOrEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:150]; NSLayoutConstraint *height = [NSLayoutConstraint constraintWithItem:subTitlelbl attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationGreaterThanOrEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:0]; [subTitlelbl setNumberOfLines:0]; [subTitlelbl addConstraint:width]; [subTitlelbl addConstraint:height]; return annotationView; } else return nil; } 

enter image description here

Así es como lo logré sin crear subclases en la vista de anotación, o usar API indocumentadas:

 MKAnnotationView* pinView = (MKAnnotationView*)[mapView dequeueReusableAnnotationViewWithIdentifier:@"CustomPinAnnotationView"]; // Add a custom view to the the callout to allow mutli-line text UIView *calloutView = [[UIView alloc] initWithFrame:CGRectMake(0, 10, 250, 250)]; UIView *calloutViewHeight = [[UIView alloc] initWithFrame:CGRectMake(0, 10, 1, 250)]; // The reason for this will become apparent below UILabel *title = [[UILabel alloc] initWithFrame:CGRectMake(10, 10, 250, 21)]; [title setText:<>]; [calloutView addSubview:title]; UILabel *subtitle = [[UILabel alloc] initWithFrame:CGRectMake(10, 35, 250, 250)]; [subtitle setNumberOfLines:0]; [subtitle setText:<>]; CGSize subtitleSize = [subtitle sizeThatFits:CGSizeMake(250, 250)]; [subtitle setFrame:CGRectMake(10, 35, 250, subtitleSize.height)]; [calloutView addSubview:subtitle]; [calloutView setFrame:CGRectMake(0, 10, 250, 35+subtitleSize.height+10)]; [calloutViewHeight setFrame:CGRectMake(0, 0, 1, 35+subtitleSize.height+10)]; pinView.leftCalloutAccessoryView = calloutView; pinView.rightCalloutAccessoryView = calloutViewHeight; // The height of the callout is calculated by the right accessory *not* the left, so this fake view is required 

Puede personalizar la fuente / color del texto ajustando el title y los subtitle consecuencia.

Claro que es un truco, pero logra los resultados deseados sin crear subclases, y te permite personalizar con los botones / imágenes adicionales que calloutView agregar calloutView (y aún puedes colocar botones en la vista derecha de accesorios si deseo, siempre y cuando conserves la altura).

No se pueden hacer dos líneas en una llamada sin entrar en API no compatibles. Si haces eso, tu aplicación será rechazada.

Si tiene un iPad, puede ver un ejemplo de texto destacado personalizado. Su llamada se transforma en una vista emergente, que se adhiere a la ubicación del mapa de la misma manera que una llamada. Por lo tanto, es posible que en la próxima versión de iOS, Apple expanda la API de llamadas. Por ahora estás atrapado con subtítulos de una línea.

Si realmente quieres hacer esto, tendrás que hacer tu propia clase de texto destacado y hacer que se adhiera al mapa a medida que se desplaza. Esto probablemente sería difícil.

Otra idea es falsificar una llamada. Cree una vista de anotación personalizada que contenga 2 vistas. El primero es un pin de mapa. El segundo es un rótulo. Cuando el pin recibe un toque, puede mostrar su vista de llamada. Faltará la animación “pop”, pero puedes poner tantas líneas como quieras.

Nunca lo intenté y parece que habría muchos detalles para hacerlo bien, pero podría comenzar.

Para configurar el botón, puede usar el siguiente código

 - (MKAnnotationView *) mapView:(MKMapView *)mapView viewForAnnotation:(id )annotation { MKAnnotationView *x=[[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:@"someIdentifier"]; UIButton *button=[UIButton buttonWithType:UIButtonTypeCustom]; //set the target, title, image etc. [x setRightCalloutAccessoryView:button]; return [x autorelease]; } 

No podrá hacerlo con API pública y tendrá que volver a implementar su propia vista de anotación personalizada.
Puede echarle un vistazo a este código que vuelve a implementar la vista de anotación, pero imita el iOS estándar, y luego puede enriquecerlo según sus necesidades:
http://blog.asolutions.com/2010/09/building-custom-map-annotation-callouts-part-1/

Imagen de resultado

Esta solución establece texto “justificado”, espero que sea útil:

Swift 3:

 import MapKit extension MKAnnotationView { func setCustomLines(customLines lines: [String]) { if lines.count <= 0 { return } // get longest line var longest = NSString() if let max = lines.max(by: { $1.characters.count > $0.characters.count }) { longest = max as NSString } else { fatalError("Can't get longest line.") } // get longest text width let font = UIFont.systemFont(ofSize: 15.0) let width = (longest.size(attributes: [NSFontAttributeName: font])).width // get text from lines var text = lines.first for i in 1..