Come personalizzare la bolla didascalia per MKAnnotationView?

voti
87

Attualmente sto lavorando con il MapKit e sono bloccato.

Ho una visione di annotazione personalizzata sto usando, e voglio utilizzare la proprietà immagine per visualizzare il punto sulla mappa con la mia propria icona. Ho questo bel lavoro. Ma quello che mi piacerebbe anche a che fare è quello di ignorare la visualizzazione predefinita chiamante (la bolla che si presenta con il titolo / sottotitolo quando l'icona di annotazione viene toccato). Voglio essere in grado di controllare la didascalia stessa: il MapKit fornisce accesso solo a sinistra e viste callout ausiliari giusti, ma nessun modo per fornire una visualizzazione personalizzata per la bolla didascalia, o per dargli dimensioni pari a zero, o qualsiasi altra cosa.

La mia idea era quella di ignorare selectAnnotation / deselectAnnotation nel mio MKMapViewDelegate, e quindi disegnare la mia vista personalizzata effettuando una chiamata alla mia vista annotazione personalizzata. Questo funziona, ma solo quando canShowCalloutè impostato YESnella mia abitudine classe di vista annotazione. Questi metodi non sono chiamati se ho questo insieme a NO(che è quello che voglio, in modo che la bolla di default callout non viene disegnato). Quindi non ho alcun modo di sapere se l'utente ha toccato il mio punto sulla mappa (selezionato) o toccato un punto che non fa parte del mio punto di vista di annotazione (delected esso) senza avere il default didascalia vista bolla vedere.

Ho provato ad andare giù un percorso diverso e solo la gestione di tutti gli eventi di tocco me stesso nella mappa, e io non riesco a ottenere questo lavoro. Ho letto gli altri commenti su cattura di eventi di tocco nella visualizzazione mappa, ma non sono esattamente quello che voglio. C'è un modo di scavare nella guarda la mappa di rimuovere la bolla didascalia prima di disegnare? Sono in perdita.

Eventuali suggerimenti? Mi sto perdendo qualcosa di ovvio?

È pubblicato 14/10/2009 alle 13:02
fonte dall'utente
In altre lingue...                            


9 risposte

voti
53

C'è una soluzione ancora più semplice.

Creare un costume UIView(per il richiamo).

Quindi creare una sottoclasse di MKAnnotationViewe di esclusione setSelectedcome segue:

- (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, lavoro fatto.

Risposto il 05/08/2011 a 12:16
fonte dall'utente

voti
40

detailCalloutAccessoryView

In passato questo era un dolore, ma Apple ha risolto, basta controllare la documentazione su MKAnnotationView

view = MKPinAnnotationView(annotation: annotation, reuseIdentifier: identifier)
view.canShowCallout = true
view.detailCalloutAccessoryView = UIImageView(image: UIImage(named: "zebra"))

In realtà, questo è tutto. Prende qualsiasi UIView.

Risposto il 23/07/2012 a 13:44
fonte dall'utente

voti
13

Proseguendo da @ risposta semplice e geniale di TappCandy, se si desidera animare la vostra bolla nello stesso modo di quella di default, ho prodotto questo metodo dell'animazione:

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

Sembra abbastanza complicata, ma fino a quando il punto di vostra bolla callout è progettato per essere centro-basso, si dovrebbe essere solo in grado di sostituire myBubbleWidthe myBubbleHeightcon il proprio formato per farlo funzionare. E ricordatevi di assicurarsi che il proprio subviews hanno la loro autoResizeMaskproprietà impostata a 63 (vale a dire "tutti") in modo che scalano correttamente nell'animazione.

: -Joe

Risposto il 24/10/2011 a 13:41
fonte dall'utente

voti
8

Ho trovato questo per essere la soluzione migliore per me. Dovrete usare una certa creatività per fare le proprie personalizzazioni

Nella vostra MKAnnotationViewsottoclasse, è possibile utilizzare

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

E se l' subviewè una UICalloutView, allora si può avvitare con essa, e ciò che è al suo interno.

Risposto il 31/08/2011 a 21:36
fonte dall'utente

voti
6

Ho avuto lo stesso problema. V'è una seria di post di blog su questo argomento su questo blog http://spitzkoff.com/craig/?p=81 .

Usando solo il MKMapViewDelegatenon aiuta voi qui e sottoclassi MKMapViewe cercando di estendere le funzionalità esistenti, inoltre, non ha funzionato per me.

Quello che ho finito per fare è quello di creare il mio CustomCalloutViewche sto avendo in cima alla mia MKMapView. È possibile lo stile questo punto di vista in qualsiasi modo si desidera.

Il mio CustomCalloutViewha un metodo simile a questo:


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

Ci vuole un MKAnnotationoggetto e imposta il proprio titolo, in seguito chiama altri due metodi che sono abbastanza brutto che regolano la larghezza e la dimensione dei contenuti callout e poi disegnano il fumetto intorno ad esso nella posizione corretta.

Infine la vista è aggiunto come una visualizzazione secondaria al mapview. Il problema di questa soluzione è che è difficile mantenere il callout nella posizione corretta quando la cartina viene fatta scorrere. Sto solo nascondendo la didascalia nel metodo delegato mappa di vista su un cambiamento regione per risolvere questo problema.

C'è voluto del tempo per risolvere tutti quei problemi, ma ora la didascalia quasi si comporta come quello ufficiale, ma ce l'ho nel mio stile.

Risposto il 16/10/2009 a 11:35
fonte dall'utente

voti
5

Fondamentalmente per risolvere questo, bisogna: a) impedire la bolla predefinita didascalia da venire. b) Figura quale annotazione è stato fatto clic.

Sono stato in grado di raggiungere questi: a) regolazione canShowCallout NO sottoclassi b), MKPinAnnotationView e sovrascrivendo i metodi touchesBegan e touchesEnd.

Nota: è necessario per gestire gli eventi touch per il MKAnnotationView e non MKMapView

Risposto il 20/11/2009 a 12:22
fonte dall'utente

voti
3

Ho appena vengo con un approccio, l'idea è

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

Qui - TestView è una UIViewdi dimensioni 320x100 - showCallout è BOOL - [self animateIn];è la funzione che fa animazione vista come UIAlertView.

Risposto il 26/01/2012 a 12:08
fonte dall'utente

voti
1

Ho spinto il mio fork del eccellente SMCalloutView che risolve il problema di fornire una visualizzazione personalizzata per didascalie e permettendo larghezze flessibili / altezze abbastanza indolore. Ancora alcune stranezze a lavorare fuori, ma è abbastanza funzionale finora:

https://github.com/u10int/calloutview

Risposto il 18/10/2012 a 00:04
fonte dall'utente

voti
1

È possibile utilizzare leftCalloutView, impostando annotation.text a @""

Di seguito riportiamo il codice di esempio:

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 = @" ";            
Risposto il 14/04/2011 a 10:18
fonte dall'utente

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