Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to display 2 lines of text for subtitle of MKAnnotation and change the image for the button on the right?

I am looking at Apple's MapCallouts example for map annotations and callouts (==bubbles that appear when you click on a pin). Every annotation there has coordinates, title and subtitle. I would like to display subtitle in 2 lines, i tried with:

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

but the text "Second line text" stays in one line and makes bubble wider.I get this:

enter image description here

I would also like to change image of the button to one of my own's, the code that sets the button is currently like this:

UIButton* rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];

Any ideas?

EDIT: I tried 7KV7's advice. Button change is successful, but i still cant get subtitles in 2 lines. My code:

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;

I get this:

enter image description here

like image 212
DixieFlatline Avatar asked Apr 29 '11 11:04

DixieFlatline


4 Answers

plz use this

 - (MKAnnotationView *) mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)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

like image 178
balkaran singh Avatar answered Nov 07 '22 05:11

balkaran singh


- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)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;
}

UPDATE

The default style for annotations only supports the title and subtitle. Neither title nor subtitle can include line breaks. You cannot do this without subclassing.

To use a custom view review Apple's sample code:

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

I also think there is a problem in your code

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 has a frame (0, 15, 50, 50) and l2 has (0, 30, 50, 50). Wont these two overlap? I mean l1 will start from y=15 and its height is 50. so when l2 starts from 30 it may overlap.. Can you pls check by changing the frames

like image 37
visakh7 Avatar answered Nov 07 '22 07:11

visakh7


This is how I achieved it without subclassing the annotation view, or using undocumented APIs:

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:<<your single-line title text>>];
[calloutView addSubview:title];
UILabel *subtitle = [[UILabel alloc] initWithFrame:CGRectMake(10, 35, 250, 250)];
[subtitle setNumberOfLines:0];
[subtitle setText:<<your multi-line title text>>];
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

You can customize the font/color of the text by adjusting title and subtitle accordingly.

Sure it's a bit of a hack, but it achieves the desired results without subclassing, and allows you to customize with whatever additional buttons/images you'd like to add calloutView (and you can still place buttons in the right-accessory view if you wish, as long as you retain the height).

like image 3
Karl White Avatar answered Nov 07 '22 06:11

Karl White


Two lines in a callout can't be done without getting into unsupported APIs. If you do that, your app will be rejected.

If you have an iPad, you can see an example of a customized callout. Their callout transforms into a popout view, which sticks to the map location in the same way as a callout. So it may be that in the next version of iOS, Apple will expand the callout API. For now you're stuck with one line subtitles.

If you really want to do this, you'll have to make your own callout class and make it stick to the map as it's scrolled. This would probably be difficult.

Another idea is to fake a callout. Make a custom annotation view containing 2 views. The first is a map pin. The second is a callout. When the pin receives a touch, you can unhide your callout view. It will be missing the "pop" animation, but you can put as many lines in as you like.

I've never tried this and it sounds like there would be lots of details to get right, but it might give you a start.

like image 2
nevan king Avatar answered Nov 07 '22 07:11

nevan king