88

私は現在 mapkit で作業しており、立ち往生しています。

使用しているカスタム注釈ビューがあり、イメージ プロパティを使用して、独自のアイコンでマップ上のポイントを表示したいと考えています。私はこれでうまくいきました。しかし、私がやりたいことは、デフォルトの吹き出しビュー (注釈アイコンに触れたときにタイトル/サブタイトルとともに表示されるバブル) をオーバーライドすることです。吹き出し自体を制御できるようにしたい: マップキットは、左右の補助的な吹き出しビューへのアクセスのみを提供しますが、吹き出しの吹き出しのカスタム ビューを提供したり、サイズをゼロにしたり、その他のものを提供したりする方法はありません。

私の考えは、自分の selectAnnotation/deselectAnnotation をオーバーライドMKMapViewDelegateし、カスタム注釈ビューを呼び出して独自のカスタム ビューを描画することでした。これは機能しますが、カスタム アノテーション ビュー クラスでcanShowCalloutが に設定されている場合のみです。YESこれを設定している場合、これらのメソッドは呼び出されませんNO(これが必要なので、デフォルトの吹き出しバブルは描画されません)。そのため、ユーザーがマップ上のポイントに触れた (選択した) か、注釈ビューの一部ではないポイントに触れた (削除した) かを知る方法はありません。

別の道をたどって、マップ内のすべてのタッチイベントを自分で処理しようとしましたが、これがうまくいかないようです。マップ ビューでタッチ イベントをキャッチすることに関連する他の投稿を読みましたが、それらは私が望んでいるものではありません。描画する前に吹き出しの吹き出しを削除するためにマップ ビューを掘り下げる方法はありますか? 私は途方に暮れています。

助言がありますか?明らかな何かが欠けていますか?

4

9 に答える 9

54

さらに簡単な解決策があります。

カスタムを作成しますUIView(コールアウト用)。

次に、次のようにサブクラスを作成してMKAnnotationViewオーバーライドsetSelectedします。

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

    if(selected)
    {
        //Add your custom view to self...
    }
    else
    {
        //Remove your custom view...
    }
}

ブーム、仕事は終わりました。

于 2011-08-05T11:16:40.953 に答える
40

detailCalloutAccessoryView

昔はこれは苦痛でしたが、Appleはそれを解決しました。MKAnnotationViewのドキュメントを確認してください。

view = MKPinAnnotationView(annotation: annotation, reuseIdentifier: identifier)
view.canShowCallout = true
view.detailCalloutAccessoryView = UIImageView(image: UIImage(named: "zebra"))

本当に、それだけです。任意のUIViewを取得します。

于 2012-07-23T12:44:23.497 に答える
13

@TappCandy の見事にシンプルな答えから続けて、デフォルトのバブルと同じ方法でバブルをアニメーション化する場合は、次のアニメーション メソッドを作成しました。

- (void)animateIn
{   
    float myBubbleWidth = 247;
    float myBubbleHeight = 59;

    calloutView.frame = CGRectMake(-myBubbleWidth*0.005+8, -myBubbleHeight*0.01-2, myBubbleWidth*0.01, myBubbleHeight*0.01);
    [self addSubview:calloutView];

    [UIView animateWithDuration:0.12 delay:0.0 options:UIViewAnimationOptionCurveEaseOut animations:^(void) {
        calloutView.frame = CGRectMake(-myBubbleWidth*0.55+8, -myBubbleHeight*1.1-2, myBubbleWidth*1.1, myBubbleHeight*1.1);
    } completion:^(BOOL finished) {
        [UIView animateWithDuration:0.1 animations:^(void) {
            calloutView.frame = CGRectMake(-myBubbleWidth*0.475+8, -myBubbleHeight*0.95-2, myBubbleWidth*0.95, myBubbleHeight*0.95);
        } completion:^(BOOL finished) {
            [UIView animateWithDuration:0.075 animations:^(void) {
                calloutView.frame = CGRectMake(-round(myBubbleWidth/2-8), -myBubbleHeight-2, myBubbleWidth, myBubbleHeight);
            }];
        }];
    }];
}

かなり複雑に見えますが、吹き出しのポイントが中央下部になるように設計されている限り、myBubbleWidthmyBubbleHeightを独自のサイズに置き換えるだけで機能します。また、サブビューのautoResizeMaskプロパティが 63 (つまり「すべて」) に設定されていることを確認して、アニメーションで正しくスケーリングされるようにしてください。

:-ジョー

于 2011-10-24T12:41:51.993 に答える
8

これが私にとって最良の解決策であることがわかりました。独自のカスタマイズを行うには、ある程度の創造性を使用する必要があります

サブクラスでは、MKAnnotationView使用できます

- (void)didAddSubview:(UIView *)subview{
    int image = 0;
    int labelcount = 0;
    if ([[[subview class] description] isEqualToString:@"UICalloutView"]) {
        for (UIView *subsubView in subview.subviews) {
            if ([subsubView class] == [UIImageView class]) {
                UIImageView *imageView = ((UIImageView *)subsubView);
                switch (image) {
                    case 0:
                        [imageView setImage:[UIImage imageNamed:@"map_left"]];
                        break;
                    case 1:
                        [imageView setImage:[UIImage imageNamed:@"map_right"]];
                        break;
                    case 3:
                        [imageView setImage:[UIImage imageNamed:@"map_arrow"]];
                        break;
                    default:
                        [imageView setImage:[UIImage imageNamed:@"map_mid"]];
                        break;
                }
                image++;
            }else if ([subsubView class] == [UILabel class]) {
                UILabel *labelView = ((UILabel *)subsubView);
                switch (labelcount) {
                    case 0:
                        labelView.textColor = [UIColor blackColor];
                        break;
                    case 1:
                        labelView.textColor = [UIColor lightGrayColor];
                        break;

                    default:
                        break;
                }
                labelView.shadowOffset = CGSizeMake(0, 0);
                [labelView sizeToFit];
                labelcount++;
            }
        }
    }
}

が の場合subviewは、UICalloutViewそれとその中身をいじることができます。

于 2011-08-31T20:36:46.700 に答える
6

私も同じ問題を抱えていました。このブログhttp://spitzkoff.com/craig/?p=81には、このトピックに関する深刻なブログ投稿があります。

ここではを使用するだけでMKMapViewDelegateは役に立たず、サブクラスMKMapView化して既存の機能を拡張しようとしてもうまくいきませんでした。

私がやったことは、私が自分のCustomCalloutView上に持っている自分自身を作成することですMKMapView。このビューのスタイルは自由に設定できます。

CustomCalloutViewはこれに似た方法を持っています:


- (void) openForAnnotation: (id)anAnnotation
{
    self.annotation = anAnnotation;
    // remove from view
    [self removeFromSuperview];

    titleLabel.text = self.annotation.title;

    [self updateSubviews];
    [self updateSpeechBubble];

    [self.mapView addSubview: self];
}

オブジェクトを受け取り、MKAnnotation独自のタイトルを設定します。その後、コールアウト コンテンツの幅とサイズを調整し、適切な位置に吹き出しを描画する非常に醜い他の 2 つのメソッドを呼び出します。

最後に、ビューがサブビューとして mapView に追加されます。このソリューションの問題点は、マップ ビューをスクロールしたときに吹き出しを正しい位置に保つのが難しいことです。この問題を解決するために、地域の変更時にマップ ビューのデリゲート メソッドでコールアウトを非表示にしています。

これらの問題をすべて解決するのに時間がかかりましたが、今では吹き出しはほぼ公式のもののように動作しますが、私は自分のスタイルでそれを持っています.

于 2009-10-16T10:35:13.873 に答える
5

基本的にこれを解決するには、次のことを行う必要があります。 a) デフォルトのコールアウト バブルが表示されないようにします。b) どの注釈がクリックされたかを把握します。

a) canShowCallout を NO に設定 b) MKPinAnnotationView をサブクラス化し、touchesBegan メソッドと touchesEnd メソッドをオーバーライドすることで、これらを実現できました。

注: MKMapView ではなく MKAnnotationView のタッチ イベントを処理する必要があります。

于 2009-11-20T11:22:24.777 に答える
3

私はちょうどアプローチを思いついた、ここでのアイデアは

  // Detect the touch point of the AnnotationView ( i mean the red or green pin )
  // Based on that draw a UIView and add it to subview.
- (void)mapView:(MKMapView *)mapView regionWillChangeAnimated:(BOOL)animated
{
    CGPoint newPoint = [self.mapView convertCoordinate:selectedCoordinate toPointToView:self.view];
//    NSLog(@"regionWillChangeAnimated newPoint %f,%f",newPoint.x,newPoint.y);
    [testview  setCenter:CGPointMake(newPoint.x+5,newPoint.y-((testview.frame.size.height/2)+35))];
    [testview setHidden:YES];
}

- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated
{
    CGPoint newPoint = [self.mapView convertCoordinate:selectedCoordinate toPointToView:self.view];
//    NSLog(@"regionDidChangeAnimated newPoint %f,%f",newPoint.x,newPoint.y);
    [testview  setCenter:CGPointMake(newPoint.x,newPoint.y-((testview.frame.size.height/2)+35))];
    [testview setHidden:NO];
}

- (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view 
{  
    NSLog(@"Select");
    showCallout = YES;
    CGPoint point = [self.mapView convertPoint:view.frame.origin fromView:view.superview];
    [testview setHidden:NO];
    [testview  setCenter:CGPointMake(point.x+5,point.y-(testview.frame.size.height/2))];
    selectedCoordinate = view.annotation.coordinate;
    [self animateIn];
}

- (void)mapView:(MKMapView *)mapView didDeselectAnnotationView:(MKAnnotationView *)view 
{
    NSLog(@"deSelect");
    if(!showCallout)
    {
        [testview setHidden:YES];
    }
}

ここで - testview は 320x100UIViewのサイズです - showCallout は BOOL です -[self animateIn];のようなアニメーションを表示する関数ですUIAlertView

于 2012-01-26T11:08:28.037 に答える
1

コールアウトのカスタム ビューを提供し、柔軟な幅/高さを非常に簡単に許可することで問題を解決する優れた SMCalloutView のフォークをプッシュしました。まだ解決すべきいくつかの癖がありますが、これまでのところかなり機能的です。

https://github.com/u10int/calloutview

于 2012-10-17T23:04:09.457 に答える
1

annotation.text を @" " に設定して、leftCalloutView を使用できます。

以下のコード例をご覧ください。

pinView = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:defaultPinID];
if(pinView == nil){
    pinView = [[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:defaultPinID] autorelease];       
}
CGSize sizeText = [annotation.title sizeWithFont:[UIFont fontWithName:@"HelveticaNeue" size:12] constrainedToSize:CGSizeMake(150, CGRectGetHeight(pinView.frame))                                 lineBreakMode:UILineBreakModeTailTruncation];
pinView.canShowCallout = YES;    
UILabel *lblTitolo = [[UILabel alloc] initWithFrame:CGRectMake(2,2,150,sizeText.height)];
lblTitolo.text = [NSString stringWithString:ann.title];
lblTitolo.font = [UIFont fontWithName:@"HelveticaNeue" size:12];
lblTitolo.lineBreakMode = UILineBreakModeTailTruncation;
lblTitolo.numberOfLines = 0;
pinView.leftCalloutAccessoryView = lblTitolo;
[lblTitolo release];
annotation.title = @" ";            
于 2011-04-14T09:18:18.583 に答える