2013-03-06 109 views
31

这是我的代码。我想添加自己的自定义标注视图而不是iOS默认。我知道只有左侧标注和右侧标注视图,但我需要使用自己的背景和标签添加视图工具提示类型。如何在地图的注释标注中添加自定义视图

- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation 
    { 
     MKAnnotationView *userAnnotationView = nil; 
     if ([annotation isKindOfClass:MKUserLocation.class]) 
     { 
      userAnnotationView = (MKAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:@"UserLocation"]; 
      if (userAnnotationView == nil) { 
      userAnnotationView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:@"UserLocation"]; 
      } 
      else 
       userAnnotationView.annotation = annotation; 

      userAnnotationView.enabled = YES; 


      userAnnotationView.canShowCallout = YES; 
      userAnnotationView.image = [UIImage imageNamed:@"map_pin.png"]; 
      UIView *view = [[UIView alloc]initWithFrame:CGRectMake(0,0,141,108)]; 
      view.backgroundColor = [UIColor clearColor]; 
      UIImageView *imgView = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"toltip.png"]]; 
      [view addSubview:imgView]; 
      userAnnotationView.leftCalloutAccessoryView = view; 



      return userAnnotationView; 
     } 

} 

Image for reference

+0

http://stackoverflow.com/questions/9814988/mkmapview-instead-of-annotation-pin-a-custom-view – 2013-03-06 07:34:00

+0

https://github.com/ okhanokbay/MapViewPlus – 2018-03-10 12:56:23

回答

129

我有同样的问题,并最终做以下的事情:

当我收到的MapView委托回调

-(void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view 

(这是当我想告诉我的自定义CalloutView时间)

我用收到的参数*(MKAnnotationView )查看查看(这是一个引脚图)和简单的我的自定义视图添加到使用

[view addSubview:customView]; 

该引脚鉴于这将增加对销鉴于顶部自定义视图,所以如果我们希望它是上面的引脚,我们必须瓒GE自定义视图中心财产是这样的:

CGRect customViewRect = customView.frame; 
     CGRect rect = CGRectMake(-customViewRect.size.width/2, -customViewRect.size.height-7, customViewRect.size.width, customViewRect.size.height); 
     customView.frame = rect; 
[view addSubview:customView]; 

对我来说,它看起来像这样

enter image description here

注意

有一个警告然而其可以方便地固定,您的自定义视图将忽略触摸事件,因为mapView以不同方式处理触摸。这里有一个速战速决

1)子类MKAnnotationView(或MKPinAnnotationView在MapView的委托取决于你的需要)

2)

- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation 

使用你的子类而不是MKAnnotationView/MKPinAnnot ationView

3)在子类.m文件覆盖两个方法如下:

- (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent*)event 
{ 
    UIView* hitView = [super hitTest:point withEvent:event]; 
    if (hitView != nil) 
    { 
     [self.superview bringSubviewToFront:self]; 
    } 
    return hitView; 
} 

- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent*)event 
{ 
    CGRect rect = self.bounds; 
    BOOL isInside = CGRectContainsPoint(rect, point); 
    if(!isInside) 
    { 
     for (UIView *view in self.subviews) 
     { 
      isInside = CGRectContainsPoint(view.frame, point); 
      if(isInside) 
       break; 
     } 
    } 
    return isInside; 
} 

全部完成!

+2

令人惊叹!为什么不选择这个解决方案呢? – fdiaz 2013-11-13 12:20:55

+1

工程就像一个魅力,谢谢!你是怎么知道这件事的?我花了很多时间摆弄框架和''sizeToFit'',但它们都不起作用! – 2013-12-25 21:06:53

+1

@Gaurav接受我的回答是否有用 – haawa 2013-12-31 10:57:06

1

我刚为我的地图视图创建了一个自定义标注,以避免点击时标注消失的问题。 Here是我采取的步骤与Gist。

+0

我已经实现了你的代码,但它不工作。你能帮我么 ? – 2015-09-24 12:22:52

10

我创建了一个库来显示自定义标注。

DXCustomCallout-ObjC

我们可以传递标注任何自定义视图! 它也支持UIControls的事件。

Custom Callout

+0

这真棒,它适用于iOS 9吗? – Supertecnoboff 2016-01-03 18:52:04

+0

刚刚在iOS 9上使用它,似乎很好。 – theLastNightTrain 2016-01-06 21:50:35

+0

嗨,如何在选择其他注释时隐藏标注? – Misha 2016-01-19 06:36:54

2

为最佳答案以上斯威夫特

这样可以节省几分钟重写本身。 !

注:

有一点需要注意哪些但可以很容易固定,自定义视图将忽略触摸事件,因为MapView的与触摸的工作方式不同。这里有一个快速的解决办法:

1)子类MKAnnotationView(或MKPinAnnotationView取决于你的需要)

2)在你的MapView委托

func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? 

使用你的子类,而不是MKAnnotationView/MKPinAnnotationView

3)在您的子类.m文件中覆盖两种方法,如下所示:

override func hitTest(point: CGPoint, withEvent event: UIEvent?) -> UIView? { 

    let hitView = super.hitTest(point, withEvent: event) 

    if (hitView != nil) 
    { 
     self.superview?.bringSubviewToFront(self) 
    } 

    return hitView; 

} 

override func pointInside(point: CGPoint, withEvent event: UIEvent?) -> Bool { 

    let rect = self.bounds 
    var isInside = CGRectContainsPoint(rect, point) 

    if(!isInside) { 
     for view in self.subviews { 

      isInside = CGRectContainsPoint(view.frame, point) 
      break; 
     } 
    } 

    return isInside 
} 
+0

我认为你的休息应放在一个if isInside {} – xxtesaxx 2016-12-31 07:13:06

相关问题