2

I have a custom UIView that I am displaying as a callout when the user clicks on a custom annotation on an MKMapView.

To achieve this I have subclassed MKAnnotationView and overloaded the -setSelected:selected animated: method as suggested in this answer. Basically, I am adding my custom view as a subview of my MKAnnotationView subclass.

The problem is that I can't interact with the callout, which contains a button and a scrollable webview, at all. What's more, if the callout hides an annotation and I press the callout at the approximate location of that hidden annotation, the callout will get dismissed and a new one will be shown.

// TPMapAnnotationView.m
@implementation TPMapAnnotationView
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
    [super setSelected:selected animated:animated];

    if(selected)
    {
        TPMapAnnotation* anno = ((TPMapAnnotation*)self.annotation);
        QuickInfoView* qi = [[QuickTabView alloc] initWithFrame:CGRectMake(0, 0, 440, 300)];
        [qi displayDataForAnnotation:anno];
        [self addSubview:qi];
        // some animiation code that doesn't change things either way
    }
    else
    {
        [[self.subviews objectAtIndex:0] removeFromSuperview];
    }
}

The code below creates the TPMapAnnotationView.

// this is in the view controller that contains the MKMapView
- (MKAnnotationView *) mapView:(MKMapView *) mapView viewForAnnotation:(id) annotation 
{  
    if ([annotation isKindOfClass:[TPMapAnnotation class]])
    {
        TPMapAnnotationView *customAnnotationView = (TPMapAnnotationView *)[myMap dequeueReusableAnnotationViewWithIdentifier:@"TPAnn"];
        if (customAnnotationView == nil)
        {
            customAnnotationView = [[TPMapAnnotationView alloc] initWithAnnotation:annotation 
                                                                reuseIdentifier:@"TPAnn"];
        }
        [customAnnotationView setImage:annotationImage];
        return customAnnotationView;
    }
    return nil; // blue radar circle for MKUserLocation class.
}
Community
  • 1
  • 1
dandan78
  • 13,328
  • 13
  • 64
  • 78

2 Answers2

6

This is a well known problem. Anything you add on AnnotationView will not detect touches. There is good open source project for this problem. http://dev.tuyennguyen.ca/wp-content/uploads/2011/03/CustomMapAnnotationBlogPart1.zip, http://dev.tuyennguyen.ca/wp-content/uploads/2011/03/CustomMapAnnotationBlogPart21.zip

EDIT:

Yes. I also tried hard to add uibuttons to my own custom annotationView but then I stumbled upon this project and found that his custom annotationView is actually a annotation.

Anyway if you want to to change height of annotatioView then you can set

- (MKAnnotationView *) mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>) annotation{

 calloutMapAnnotationView.contentHeight = height;
 calloutMapAnnotationView.titleHeight = 25;
}

here, titleHeight is property added to CalloutMapAnnotationView which determines height of "gloss" in drawRectMethod

- (void)drawRect:(CGRect)rect {
glossRect.size.height = self.titleHeight;
}

if you are having any difficulty please let me know.

And also the link to original blogpost: http://dev.tuyennguyen.ca/?p=298

chatur
  • 2,365
  • 4
  • 24
  • 38
  • I eventually went with a modification of that code. It was a bit of work, tho, because it took me a while to figure out that the callout was in fact a custom-drawn map annotation. In addition, the drawing code is a bit cryptic and generally difficult to modify. – dandan78 Jan 06 '12 at 12:21
  • Thanks, chatur, but I managed to get it working over a week ago. I was merely pointing out that the code was a bit tough to rework. Anyway, my case was somewhat more complex so I had to dive into `drawRect` and other drawing code. It was certainly easier than starting from scratch, but again, not quite a walk in the park. – dandan78 Jan 07 '12 at 14:15
  • @chatur Could you check out my question about animated overlays in map view http://stackoverflow.com/questions/20558591/animated-gif-not-working-in-mkmapview-overlay-using-mkoverlayrenderer?noredirect=1#comment30789828_20558591? Any help would be appreciated. – wigging Dec 18 '13 at 04:45
5

I resolved this problem. Click anything in CalloutView,the map will not get touch.My calloutview is custom have tabbleview

1 - In file MapviewController.h you will add delegate : UIGestureRecognizerDelegate

2 - and in file MapViewController.m implement method - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch

-In my mapView when you click 1 time on Map it will go in this method 3 time. So I limit touch will action.the first touch will action. - In myCalloutView have tabbleView, if tabbleView receive touch It will return false touch for Map, it will make your tabbleview can get touch.It same for your button.

Note : in NSlog hit test View : will have name of view item you want it have touch. example my view : isEqualToString:@"UITableViewCellContentView"]

static int count=0;
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch{
    NSLog(@"hit test view %@",[touch view]);    
    if(count >0 && count<=2)
    {
        count++;
        count=count%2;
        return FALSE;
    }
    count++;      
    if ([[[[touch view] class] description] isEqualToString:@"UITableViewCellContentView"]) {
        return FALSE;
    }
    return TRUE;
}
THT
  • 51
  • 1
  • 2