3

私は自分のプロジェクトの問題に苦しんでいます:

私は mapView を持っていて、以下に示す注釈を表示する必要があります (小さい (+) は私のボタンです)

私は何をしなければならないのですか

私は MKAnnotationView をサブクラス化し、次のような CustomAnnotationView.h を持っています:

@interface CustomAnnotationView : MKAnnotationView

@property (strong, nonatomic) UIImageView *calloutView;
@property (strong, nonatomic) UIButton *pinButton;
@property (strong, nonatomic) UIView *annView;

- (void)setSelected:(BOOL)selected animated:(BOOL)animated;
- (void)animateCalloutAppearance;

私の CustomAnnotationView.m

- (void)setSelected:(BOOL)selected animated:(BOOL)animated{
    [super setSelected:selected animated:animated];


    if(selected)
    {
        //building my custom animation 
        annView = [[ UIView alloc ] initWithFrame:(CGRectMake(0, 0, 30, 30)) ];

        annView.frame =CGRectMake(0, 0, 200, 50);

        calloutView = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"customcallout.png"]];


        [calloutView setFrame:CGRectMake(-25, 50, 0, 0)];
        [calloutView sizeToFit];


        [self animateCalloutAppearance];

        //I tried to add a button here but I could't do it like it should be
        [annView addSubview:calloutView];

        [self addSubview:annView];

    }
    else
    {
        //Remove your custom view...

        [annView removeFromSuperview];
    }
}

- (void)didAddSubview:(UIView *)subview{


        if ([[[subview class] description] isEqualToString:@"UICalloutView"]) {
            for (UIView *subsubView in subview.subviews) {
                if ([subsubView class] == [UIImageView class]) {
                    UIImageView *imageView = ((UIImageView *)subsubView);
                    [imageView removeFromSuperview];
                }else if ([subsubView class] == [UILabel class]) {
                    UILabel *labelView = ((UILabel *)subsubView);
                    [labelView removeFromSuperview];
                }
            }

    }
}


- (void)animateCalloutAppearance {
    CGFloat scale = 0.001f;
    calloutView.transform = CGAffineTransformMake(scale, 0.0f, 0.0f, scale, 0, -50);

    [UIView animateWithDuration:0.15 delay:0 options:UIViewAnimationCurveEaseOut animations:^{
        CGFloat scale = 1.1f;
        calloutView.transform = CGAffineTransformMake(scale, 0.0f, 0.0f, scale, 0, 2);

    } completion:^(BOOL finished) {
        [UIView animateWithDuration:0.1 delay:0 options:UIViewAnimationCurveEaseInOut animations:^{
            CGFloat scale = 0.95;
            calloutView.transform = CGAffineTransformMake(scale, 0.0f, 0.0f, scale, 0, -2);

        } completion:^(BOOL finished) {
            [UIView animateWithDuration:0.075 delay:0 options:UIViewAnimationCurveEaseInOut animations:^{
                CGFloat scale = 1.0;
                calloutView.transform = CGAffineTransformMake(scale, 0.0f, 0.0f, scale, 0, 0);

            } completion:nil];
        }];
    }];
}

@end

これにより、カスタム注釈を地図上に表示できますが、ボタンを配置する方法がわかりません。もちろん、このボタンはコールバックのようなクリックに応答できるはずですcalloutAccessoryControlTapped:

実用的なコード例やアイデアをお持ちの方にお願いします。ありがとうございました。

4

2 に答える 2

4

クラスで使用- (UIView*)hitTestしてこれを解決しました。吹き出しビュー用に別の nib を用意し、hittest を使用して、(吹き出し nib からリンクされた)CustmAnnotationView.m名前の付いた UILabel がクリックされたかどうかを判断します。directionsButton

- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
    if (selected) {
        calloutVisible = YES;
        hitTestBuffer = NO;
        self.calloutView = [[[NSBundle mainBundle] loadNibNamed:@"CalloutView" owner:self options:nil] objectAtIndex:0];  
        [directionsButton setFont:[UIFont fontWithName:@"DIN-Medium" size:12.0f]];
        [calloutView setFrame:CGRectMake(calloutView.frame.origin.x, calloutView.frame.origin.y, 280, calloutView.frame.size.height)];          
        [calloutView setAlpha:0.0f];    
        [self addSubview:calloutView];
        [self sendSubviewToBack:calloutView];


        [UIView animateWithDuration:0.3f delay:0.0f options:0 animations:^{     
            [calloutView setAlpha:1.0f];
        } completion:^(BOOL finished) {
        }];

        [super setSelected:selected animated:animated];

    } else {
        calloutVisible = NO;

        CGRect newFrame = self.frame;
        newFrame.size.width = 52;
        self.frame = newFrame;

        [UIView animateWithDuration:0.3f delay:0.0f options:0 animations:^{
            [calloutView setAlpha:0.0f];
        } completion:^(BOOL finished) {
            [calloutView removeFromSuperview];
        }];
    }
}


- (void)directionsPressed
{
    if ([parent respondsToSelector:@selector(directionsPressed:)])
        [parent performSelector:@selector(directionsPressed:) withObject:self.stockist];
}


- (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
    if (calloutVisible) {
        CGPoint hitPoint = [calloutView convertPoint:point toView:directionsButton];
        if ([calloutView pointInside:hitPoint withEvent:event]) {
            if (!hitTestBuffer) {
                [self directionsPressed];
                hitTestBuffer = YES;
            }
            return [directionsButton hitTest:point withEvent:event];
        } else {
            hitTestBuffer = NO;
        }
    }
    return [super hitTest:point withEvent:event];
}

私のコードparentには、現在の VC があります。これはおそらく最もきちんとした方法ではありませんが、当時は機能していました。

コールアウトは次のようになります。

叫ぶ

いくつかのブール値calloutVisibleを設定hitTestBufferし、ボタンが表示されているときにのみクリックできるようにします。

于 2012-11-14T14:27:36.097 に答える
2

あなたの問題を解決するために、私はApple の WeatherMap の例で少し遊んで、あなたの問題に対する有効な解決策を思いつきました。

コードをWeatherAnnotationView.mファイルに追加し (アニメーション コードを除く)、その上にボタンを表示し、タッチ イベントに応答するコードを追加しました。

-(void)annotationButtonClicked{
    NSLog(@"** button clicked");
}

- (void)setSelected:(BOOL)selected animated:(BOOL)animated{
    if(selected)
    {
        //building my custom animation
        annView = [[ UIView alloc ] initWithFrame:(CGRectMake(0, 0, 30, 30)) ];

        annView.frame =CGRectMake(0, 0, 200, 50);

        calloutView = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"cloudy.png"]];


        [calloutView setFrame:CGRectMake(-25, 50, 0, 0)];
        [calloutView sizeToFit];
        [annView addSubview:calloutView];


        /* BUTTON CODE */
        UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(0,0,20,20)];
        button.backgroundColor = [UIColor orangeColor];

        [button addTarget:self action:@selector(annotationButtonClicked) forControlEvents:UIControlEventTouchUpInside];
        [annView addSubview:button];
        /* END Of BUTTON CODE */

        [self addSubview:annView];

    }
    else
    {
        //Remove your custom view...
        [annView removeFromSuperview];
    }

}

にボタンを追加しようとした方法を投稿していないannViewため、あなたのアプローチで何が機能していなかったのかを理解するのは困難です。この種の問題に対する一般的なアプローチは、一度に 1 つのコードを削除してアプリを実行することです。まず、アニメーション コードを削除してみてください。次に、ボタンで動作するコードができるまで、 を削除して、 とボタンcalloutViewのみを残します。annViewその後、以前に削除した部分 (アニメーション、calloutView) を一度に 1 つずつ追加し、ボタンの機能を停止させている原因を確認します。

これが何らかの形で役立つことを願っています。

于 2012-11-12T15:44:05.177 に答える