4

MKMapView注釈が選択された後、中央揃えにしようとしています。私も有効にcanShowCalloutしましたが、iOS が最初にコールアウトを表示し (画面に収まらない場合はシフトされます)、マップが移動されているようで、コールアウトが画面に完全に表示されていません。

吹き出しの位置が正しくない

吹き出しの位置がレンダリングおよび表示される前に、マップを中央に配置するにはどうすればよいですか?

4

2 に答える 2

4

私は同じことを達成したかったので、最終的に次のことを行いました。

始める前に注意事項があります。解決策がかなり醜いことはわかっています!...しかし、うまくいきます。

注: iOS 9 をターゲットにしていますが、以前のバージョンの iOS でも動作するはずです。

さて、ここに行きます:

  • まず、View Controller に新しいプロパティを作成します。@property(nonatomic, assign, getter=isPinCenteringOngoing) BOOL pinCenteringOngoing;
  • あなたのannotationViewsにmapView:viewForAnnotation:設定さcanShowCalloutれていますNO
  • mapView:didSelectAnnotationView:次のことを行います。

    - (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view
    {
        if([view isKindOfClass:$YOURANNOTATIONVIEWCLASS$.class])
        {
            if(!self.isPinCenteringOngoing)
            {
                self.pinCenteringOngoing = YES;
                [self centerMapOnSelectedAnnotationView:($YOURANNOTATIONVIEWCLASS$ *)view];
            }
            else
            {
                self.pinCenteringOngoing = NO;
            }
        }
    }
    
  • mapView:didDeselectAnnotationView:次のことを行います。

    - (void)mapView:(MKMapView *)mapView didDeselectAnnotationView:(MKAnnotationView *)view
    {
        if([view isKindOfClass:$YOURANNOTATIONVIEWCLASS$.class])
        {
            if(!self.isPinCenteringOngoing)
            {
                view.canShowCallout = NO;
            }
        }
    }
    
  • 最後に、実際の作業を行う新しいメソッドを作成します。

    - (void)centerMapOnSelectedAnnotationView:($YOURANNOTATIONVIEWCLASS$ *)view
    {
        // Center map
        CGPoint annotationCenter = CGPointMake(CGRectGetMidX(view.frame), CGRectGetMidY(view.frame));
        CLLocationCoordinate2D newCenter = [self.mapView convertPoint:annotationCenter toCoordinateFromView:view.superview];
        [self.mapView setCenterCoordinate:newCenter animated:YES];
    
        // Allow callout to be shown
        view.canShowCallout = YES;
    
        // Deselect and then select the annotation so the callout is actually displayed
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.3 * NSEC_PER_SEC), dispatch_get_main_queue(), ^(void)
        {
            [self.mapView deselectAnnotation:view.annotation animated:NO];
    
            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.1 * NSEC_PER_SEC), dispatch_get_main_queue(), ^(void)
            {
                [self.mapView selectAnnotation:view.annotation animated:NO];
            });
        });
    }
    

私の答えを完成させるために、上記のコードで私が何をしているのか、そしてなぜそれをしているのかをテキストで説明します:

  • 私が欲しいのは、注釈が画面の中央に配置され、コールアウトがその上に中央に配置されることです。
  • デフォルトで得られるものは次のとおりです。
    • 注釈を選択すると、マップで吹き出しが開き、必要に応じて吹き出しが画面に収まるようにマップが調整されます。コールアウトが注釈の上に「中央揃え」されることを標準実装が保証するわけではありません。
    • setCenterCoordinate: でマップを中央に配置すると、注釈ビューがマップの中央に配置されます。
    • 以前の 2 つのポイントを組み合わせると、注釈がマップの中央に配置されるため、吹き出しが「切り取られる」可能性がありますが、吹き出しは注釈の上に配置されません。
  • これを修正するには、次のことを行います。
    • 最初に、デフォルトで表示されるコールアウトを無効にし、すべての annotationView に対して canShowCallout を NO に設定します
    • ユーザーが注釈を選択すると、まずマップを中央に配置します
    • 次に、選択した注釈の canShowCallout を YES に設定して、吹き出しを表示できるようにします。
    • 次に、注釈を選択解除してから再度選択すると、吹き出しが実際に表示されます
    • 吹き出しが注釈の上で正しく中央に配置されるようにするには、マップの中央揃えが完了するように、選択解除/選択を少し遅らせる必要があります

私の答えが役立つことを願っています。

于 2016-07-02T01:10:16.817 に答える