Cum de a personaliza bula înștiințărilor pentru MKAnnotationView?

voturi
87

Eu sunt în prezent de lucru cu mapkit și am blocat.

Am o vedere personalizată adnotare I sînt folosire, și vreau să utilizeze proprietatea de imagine pentru a afișa punctul de pe harta cu propria mea pictogramă. Am acest lucru bine. Dar ceea ce aș dori, de asemenea, să faceți este să suprascrie vizualizarea implicită înștiințărilor (balonul care apare cu titlul / subtitrarea atunci când pictograma adnotare este atinsă). Vreau să fie în măsură să controleze în sine înștiințarea: a mapkit oferă doar acces la stânga și la dreapta înștiințări opiniile auxiliare, dar nici o modalitate de a oferi o imagine personalizată pentru balon înștiințărilor, sau pentru a da dimensiunea zero, sau orice altceva.

Ideea mea a fost de a trece peste selectAnnotation / deselectAnnotation în meu MKMapViewDelegate, și apoi trage propria mea viziune personalizată prin a face un apel la punctul meu de vedere personalizată adnotată. Aceasta funcționează, dar numai atunci când canShowCallouteste setat YESîn vederea adnotare personalizată clasa mea. Aceste metode nu sunt numite , dacă am acest set la NO(care este ceea ce vreau, astfel încât bula implicit înștiințărilor nu este desenată). Așa că am nici o modalitate de a ști dacă utilizatorul a atins punctul meu de pe hartă (o selectată) sau a atins un punct care nu face parte din vederile mele adnotare (l delected) , fără a avea implicit înștiințărilor vedere cu bule arată în sus.

Am încercat să merg pe o cale diferită și doar de manipulare toate evenimentele tactile mă pe hartă, și eu nu pot par pentru a obține acest lucru. Am citit alte posturi legate de capturare evenimente tactile în vizualizarea hartă, dar ele nu sunt exact ceea ce vreau. Există o modalitate de a săpa în vizualizarea hărții pentru a elimina bula înștiințărilor înainte de desen? Sunt la o pierdere.

Orice sugestii? Îmi scapă ceva evident?

Întrebat 14/10/2009 la 13:02
sursa de către utilizator
În alte limbi...                            


9 răspunsuri

voturi
53

Există o soluție chiar mai ușor.

Creați un obicei UIView(pentru înștiințare).

Apoi a crea o subclasă a MKAnnotationViewși suprascrie setSelecteddupă cum urmează:

- (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, treaba.

Publicat 05/08/2011 la 12:16
sursa de către utilizator

voturi
40

detailCalloutAccessoryView

În vremurile de demult aceasta a fost o durere, dar Apple a rezolvat aceasta, trebuie doar să verificați docs pe MKAnnotationView

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

Într-adevăr, asta e. Ia orice UIView.

Publicat 23/07/2012 la 13:44
sursa de către utilizator

voturi
13

Continuând de la @ răspuns strălucit simplu TappCandy lui, dacă doriți să animați bule în același mod ca și cel implicit, am produs această metodă de animație:

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

Se pare destul de complicat, dar atâta timp cât punctul de bule înștiințării este proiectat pentru a fi centru-jos, ar trebui să fie în stare să înlocuiască myBubbleWidthși myBubbleHeightcu propria dimensiune pentru ca aceasta să funcționeze. Și nu uitați să vă asigurați că subviews dvs. au de autoResizeMaskproprietate setată la 63 ( de exemplu , „toate“) , astfel încât acestea să scară corect în animație.

: -Joe

Publicat 24/10/2011 la 13:41
sursa de către utilizator

voturi
8

S-au găsit acest lucru pentru a fi cea mai bună soluție pentru mine. Va trebui să utilizați unele creativitatea pentru a face propriile particularizările

În dvs. MKAnnotationViewsubclasă, puteți utiliza

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

Și dacă subvieweste o UICalloutView, atunci puteți șurub în jurul valorii de cu ea, și ceea ce este în interiorul acestuia.

Publicat 31/08/2011 la 21:36
sursa de către utilizator

voturi
6

Am avut aceeași problemă. Există o serioasă de posturi pe blog despre acest subiect pe acest blog http://spitzkoff.com/craig/?p=81 .

Doar folosind MKMapViewDelegatenu te ajută aici și subclasarea MKMapViewși încearcă să extindă funcționalitatea existentă , de asemenea , nu au de lucru pentru mine.

Ceea ce am ajuns să fac este de a crea propria mea CustomCalloutViewcă eu sunt cu partea de sus a mea MKMapView. Puteți stil acest punct de vedere , în orice mod doriți.

Mea CustomCalloutVieware o metodă similară cu acesta:


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

Este nevoie de un MKAnnotationobiect și stabilește propriul său titlu, după aceea îl numește alte două metode care sunt destul de urât , care ajustează lățimea și dimensiunea conținutului înștiințări și apoi trage cu bule de vorbire în jurul ei în poziția corectă.

În final vizualizarea este adăugată ca subview la mapView. Problema cu această soluție este că este greu să mențină poziția de înștiințare la corectă atunci când vizualizarea hărții este defilat. Sunt doar ascunde în metoda înștiințarea delegat harta opinii cu privire la o schimbare de regiune pentru a rezolva această problemă.

A fost nevoie de ceva timp pentru a rezolva toate aceste probleme, dar acum se comportă ca aproape înștiințarea cea oficială, dar am avea în stilul meu propriu.

Publicat 16/10/2009 la 11:35
sursa de către utilizator

voturi
5

Practic pentru a rezolva acest lucru, trebuie să: a) a preveni bula implicită înștiințărilor de la venirea în sus. b) Figura care adnotare a fost apasat.

Am fost capabil să realizeze acestea, prin: a) stabilirea canShowCallout la NO subclasarea b), MKPinAnnotationView și suprascrierea metodelor touchesBegan și touchesEnd.

Notă: Trebuie să se ocupe de evenimentele de atingere pentru MKAnnotationView și nu MKMapView

Publicat 20/11/2009 la 12:22
sursa de către utilizator

voturi
3

Am venit doar cu o abordare, ideea este aici

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

Aici - testview este UIViewde dimensiune 320x100 - showCallout este bool - [self animateIn];este funcția pe care o face vedere de animație cum ar fi UIAlertView.

Publicat 26/01/2012 la 12:08
sursa de către utilizator

voturi
1

M-am împins afară furculita mea de SMCalloutView excelent, care rezolvă problema cu oferind o imagine personalizată pentru înștiințări și permițând latimi flexibile / înălțimi destul de painlessly. Încă unele ciudateniile de a lucra, dar este destul de funcțională până în prezent:

https://github.com/u10int/calloutview

Publicat 18/10/2012 la 00:04
sursa de către utilizator

voturi
1

Puteți utiliza leftCalloutView, setarea annotation.text la @“"

Mai jos codul exemplu găsit:

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 = @" ";            
Publicat 14/04/2011 la 10:18
sursa de către utilizator

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