4

カスタム マップ コールアウトを作成しました。私の吹き出しにはUIButtonsとが含まれていUITextViewます。をタップするUIButtonと、いい感じに押せます。しかし、タップUITextViewするとカーソルがタップ位置に移動し、ピンの選択が解除され、コールアウトが消えます...

hitTest:withEvent:ここのように MyAnnotationView のメソッドを実装しました: https://stackoverflow.com/a/13495795/440168

しかし、ログを見ると、[super hitTest:withEvent:]決して返されませんnil

これが私のMyAnnotationView方法です:

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

更新 1:

カスタム吹き出しビューを追加するコードは次のとおりです。

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

    // ...
}

更新 2:

MKMapView サブクラスをダーティ ハックで実装しました。しかし、これはうまくいきます!

@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

このカテゴリを使用して、ビュー階層で吹き出しを見つけます。

@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
4

1 に答える 1

1

hitTest メソッドでは、タッチ可能にするオブジェクトに応じてタッチ可能領域を定義する仮想長方形を作成する必要があります。

UICalloutView では、別のループを使用して UITextView を見つける必要があります。

その後、UITextView の寸法と UICalloutView ビューの原点に従って、この仮想四角形を定義する必要があります。

また、 for ループで continue ステートメントを使用する必要はありません。 return が開始された場合、すべてのループはすぐに停止します。

したがって、あなたの hitTest メソッドは次のようになります。

- (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;
}
于 2013-07-04T08:40:27.067 に答える