Custom map callout view hides on tap

I've made custom map callouts. My callouts contains UIButtons and UITextView . When I tap UIButton , it presses nice. But when I tap UITextView it moves cursor to tap position and then deselects pin and disappears callout...

I've implemented hitTest:withEvent: method of MyAnnotationView like here: https://stackoverflow.com/a/13495795/440168

But as I see in log, [super hitTest:withEvent:] never returns nil .

Here is my MyAnnotationView methods:

- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
{
    BOOL isInside = [super pointInside:point withEvent:event];
    if (isInside)
        return YES;

    for (UIView * subview in self.subviews)
    {
        if ([subview isKindOfClass:[NSClassFromString(@"UICalloutView") class]])
            continue;

        CGPoint inPoint = [self convertPoint:point toView:subview];
        BOOL isInside = [subview pointInside:inPoint withEvent:nil];
        if (isInside)
            return YES;
    }

    return NO;
}

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
    UIView * hitView = [super hitTest:point withEvent:event];
    if (hitView)
        return hitView;

    for (UIView * subview in self.subviews)
    {
        if ([subview isKindOfClass:[NSClassFromString(@"UICalloutView") class]])
            continue;

        CGPoint inPoint = [self convertPoint:point toView:subview];
        hitView = [subview hitTest:inPoint withEvent:event];
        if (hitView)
            return hitView;
    }

    return nil;
}

UPDATE 1:

Here is my code to add custom callout view:

- (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view
{
    for (UIView * subview in view.subviews)
        subview.hidden = YES;
    [view addSubview:self.myCalloutView];
    self.myCalloutView.center = CGPointMake(view.bounds.size.width/2,-self.myCalloutView.bounds.size.height/2);

    // ...
}

UPDATE 2:

I have just implemented my MKMapView subclass with durty hack. But this works!

@implementation HNPMapView

- (void)handleTap:(UITapGestureRecognizer *)recognizer
{
    for (UIView * v in [self findSubviewsOfClass:[MyCallout class]]) {
        CGPoint point = [recognizer locationInView:v];
        if (CGRectContainsPoint(v.bounds, point))
            return;
    }

    //[super performSelector:@selector(handleTap:) withObject:recognizer];
    void (*functionPointer)(id,SEL,...) = [MKMapView instanceMethodForSelector:@selector(handleTap:)];
    functionPointer(self,@selector(handleTap:),recognizer);
}

@end

And using this category to find callout in view hierarchy:

@interface UIView (FindSubview)
- (NSArray *)findSubviewsOfClass:(Class)class;
@end
@implementation UIView (FindSubview)
- (NSArray *)findSubviewsOfClass:(Class)class
{
    NSMutableArray * found = [NSMutableArray array];
    for (UIView * subview in self.subviews)
    {
        if ([subview isKindOfClass:class])
            [found addObject:subview];
        [found addObjectsFromArray:[subview findSubviewsOfClass:class]];
    }
    return found;
}
@end

in hitTest method you should create a virtual rectangle to define touchable area according to your object to be touchable.

in UICalloutView you should use another loop to find your UITextView.

after that you should define this virtual rectangle according your UITextView dimensions and UICalloutView view origin points.

also you don't need to use continue statement in for loop, when return initiated all loops will stop immediately already.

so your hitTest method should be like this,

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
    UIView * hitView = [super hitTest:point withEvent:event];

    if (hitView)
        return hitView;

    for (UIView * subview in self.subviews)
    {

        if ([subview isKindOfClass:[NSClassFromString(@"UICalloutView") class]]) {

            for(UIView *subTextView in subview.subviews){
                if([subTextView isKindOfClass:[UITextView class]]){

                    CGRect touchableArea = CGRectMake(subview.frame.origin.x, subview.frame.origin.y, subTextView.frame.size.width, subTextView.frame.size.height);
                    if (CGRectContainsPoint(touchableArea, point)){
                        return subTextView;
                    }
                }               
            }            
        }
    }    
    return nil;
}
链接地址: http://www.djcxy.com/p/67280.html

上一篇: 自定义地图标注动画

下一篇: 自定义地图标注视图隐藏在自来水中