在显示标注之前显示MKMapView

时间:2015-12-21 14:25:25

标签: ios mkmapview mkmapviewdelegate

我试图在选择注释后居中MKMapView。我也启用了canShowCallout但似乎iOS首先显示了标注(当它不适合屏幕时移动)然后地图被移动,导致标注不完全可见屏幕。

incorrect callout position

如何在呈现并显示标注的位置之前使地图居中?

1 个答案:

答案 0 :(得分:3)

我想完成同样的事情,最后做了以下事情。

在我开始之前要小心谨慎:我知道解决方案非常难看!...但是,嘿,它有效。

注意:我的目标是iOS 9,但它应该适用于iOS的早期版本:

好的,我们走了:

  • 首先,在视图控制器中创建一个新属性,例如:@property(nonatomic, assign, getter=isPinCenteringOngoing) BOOL pinCenteringOngoing;
  • mapView:viewForAnnotation:设置canShowCalloutNO以获取annotationViews
  • 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];
            });
        });
    }
    

为了完成我的回答,这里是对我在上面的代码中做了什么以及我为什么这样做的文字说明:

  • 我想要的是注释以屏幕为中心,并将标注置于屏幕上方。
  • 我默认获得的是:
    • 选择注释时,地图会打开标注,并在必要时调整地图以使标注适合屏幕。这个标准的实施并不能保证标注是以#34;为中心的#34;在注释之上。
    • 通过使用setCenterCoordinate:对地图居中,注释视图以地图为中心。
    • 现在前面两个点组合可能会导致标注被切断"因为注释以地图为中心,但标注不在注释之上。
  • 要解决此问题,请执行以下操作:
    • 首先禁用默认显示的标注,为每个annotationView设置canShowCallout为NO
    • 当用户选择注释时,我首先将地图居中
    • 然后我允许显示标注,为选定的注释设置canShowCallout为YES
    • 然后我取消选择然后再次选择注释,以便实际显示标注
    • 为了使标注在注释上方正确居中,我需要进行取消选择/选择稍微延迟,以便地图居中可以完成

我希望我的回答可能有用。