2015-06-11 4 views
17

У меня есть MKPointAnnotation:Настроить вид выноска MKAnnotation?

let ann = MKPointAnnotation() 
self.ann.coordinate = annLoc 
self.ann.title = "Customize me" 
self.ann.subtitle = "???" 
self.mapView.addAnnotation(ann) 

Это выглядит следующим образом:

enter image description here

Как я могу настроить вид выноски, чтобы создать свою собственную точку зрения, а не предопределенный один?

+0

Проверьте следующий ответ, ответ Анны http: // stackoverflow. com/вопросы/25631410/swift-different-images-for-annotation – casillas

+1

@casillas Нет, это настраивает аннотацию. Он не пытается настроить аннотацию, а скорее ее выноску. Я думаю, вам нужно что-то более похожее на http://stackoverflow.com/a/17772487/1271826 (это Objective-C, но идея в Swift одинакова). – Rob

+0

Вы также можете реализовать свое пользовательское представление как выноску. Это может быть примером. https://github.com/NabinRai4017/CallOutExample –

ответ

51

Прежде всего следует отметить, что простейшие изменения выноски включаются путем простой настройки свойств предоставленной системы выноски, но настройки правого и левого принадлежностей (через rightCalloutAccessoryView и leftCalloutAccessoryView). Вы можете выполнить эту настройку в viewForAnnotation.

В iOS 9 теперь у нас есть доступ к detailCalloutAccessoryView, который заменяет субтитры выноски потенциально визуально богатым представлением, при этом все еще наслаждаясь автоматическим исполнением пузырька выноски (с помощью автоматической компоновки это упрощает).

Например, вот выноска, что использовали MKSnapshotter поставлять изображение для зрения изображения в детали выноски аксессуар, как показано на WWDC 2015 видео What's New in MapKit:

enter image description here

Вы можете добиться этого с что-то вроде:

func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? { 
    if annotation is MKUserLocation { 
     return nil 
    } 

    let identifier = "MyCustomAnnotation" 

    var annotationView = mapView.dequeueReusableAnnotationViewWithIdentifier(identifier) 
    if annotationView == nil { 
     annotationView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: identifier) 
     annotationView?.canShowCallout = true 
    } else { 
     annotationView!.annotation = annotation 
    } 

    configureDetailView(annotationView!) 

    return annotationView 
} 

func configureDetailView(annotationView: MKAnnotationView) { 
    let width = 300 
    let height = 200 

    let snapshotView = UIView() 
    let views = ["snapshotView": snapshotView] 
    snapshotView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:[snapshotView(300)]", options: [], metrics: nil, views: views)) 
    snapshotView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:[snapshotView(200)]", options: [], metrics: nil, views: views)) 

    let options = MKMapSnapshotOptions() 
    options.size = CGSize(width: width, height: height) 
    options.mapType = .SatelliteFlyover 
    options.camera = MKMapCamera(lookingAtCenterCoordinate: annotationView.annotation!.coordinate, fromDistance: 250, pitch: 65, heading: 0) 

    let snapshotter = MKMapSnapshotter(options: options) 
    snapshotter.startWithCompletionHandler { snapshot, error in 
     if snapshot != nil { 
      let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: width, height: height)) 
      imageView.image = snapshot!.image 
      snapshotView.addSubview(imageView) 
     } 
    } 

    annotationView.detailCalloutAccessoryView = snapshotView 
} 

Если вы ищете более радикальную реконструкцию выноски или должны поддерживать IOS версию до 9, это занимает больше работы. Процесс влечет за собой: (а) отключение выноски по умолчанию; и (б) добавление собственного представления, когда пользователь нажимает на существующий вид аннотации (т. е. визуальный вывод на карте).

Сложность возникает при оформлении выноски, где вы должны нарисовать все, что хотите видеть. Например. если вы хотите нарисовать пузырь, чтобы вы почувствовать прикосновение вызова, вы должны сделать это сами. Но с какой-то знакомство с тем, как рисовать фигуры, изображения, текст и т.д., вы должны быть в состоянии оказать выноски, который достигает желаемого UX:

custom callout

Просто добавьте вид как подвид аннотации видеть себя и корректировать свои ограничения соответственно:

func mapView(mapView: MKMapView, didSelectAnnotationView view: MKAnnotationView) { 
    let calloutView = ... 
    calloutView.translatesAutoresizingMaskIntoConstraints = false 
    calloutView.backgroundColor = UIColor.lightGrayColor() 
    view.addSubview(calloutView) 

    NSLayoutConstraint.activateConstraints([ 
     calloutView.bottomAnchor.constraintEqualToAnchor(view.topAnchor, constant: 0), 
     calloutView.widthAnchor.constraintEqualToConstant(60), 
     calloutView.heightAnchor.constraintEqualToConstant(30), 
     calloutView.centerXAnchor.constraintEqualToAnchor(view.centerXAnchor, constant: view.calloutOffset.x) 
    ]) 
} 

См https://github.com/robertmryan/CustomMapViewAnnotationCalloutSwift для примера создания собственного зрения выноски.Это добавляет только две метки, но это иллюстрирует тот факт, что вы можете нарисовать пузырь любой желаемой формы, использовать ограничения, чтобы диктовать размер выноски и т. Д.

+0

Как указать размер с помощью calloutview? Как изменить радиус границы, и могу ли я использовать Autolayout в calloutview? – confile

+0

В моем примере я пошел в старую школу и вместо автоматического макета, я на самом деле вычислил ширину текста, используя 'sizeWithAttributes' в строке, а затем добавил в два раза радиус угла к каждой ширине (для левой и правой) и высоту (сверху и снизу), а затем на высоту, а затем добавили размер стрелки внизу. – Rob

+0

Я не видел, где вы использовали '' sizeWithAttributes''. Не могли бы вы прояснить это, тогда я могу принять ваш ответ. – confile

2

Создать Cocoa файл с ClassType MKAnnotationView

CustomeAnnotationView.h файл

@interface CustomeAnnotationView : MKAnnotationView 
@property (strong, nonatomic) UIButton *buttonCustomeCallOut; 
- (void)setSelected:(BOOL)selected animated:(BOOL)animated; 
@end 

CustomeAnnotationView.m файл

@implementation CustomeAnnotationView 

-(id)initWithFrame:(CGRect)frame 
{ 
    self = [super initWithFrame:frame]; 
    if (self) { 
     // Initialization code 
    } 
    return self; 
} 


- (void)setSelected:(BOOL)selected animated:(BOOL)animated{ 

    [super setSelected:selected animated:animated]; 

    if(selected) 
    { 



      self.buttonCustomeCallOut = [UIButton buttonWithType:UIButtonTypeCustom];//iconShare//iconShareBlue 

      [self.buttonCustomeCallOut addTarget:self action:@selector(buttonHandlerCallOut:) forControlEvents:UIControlEventTouchDown]; 
     [self.buttonCustomeCallOut setBackgroundColor:[UIColor blueColor]]; 

      [self.buttonCustomeCallOut setFrame:CGRectMake(-40,-80, 100, 100)]; 



      [self addSubview:self.buttonCustomeCallOut]; 

     [self.buttonCustomeCallOut setUserInteractionEnabled:YES]; 
    } 
    else 
    { 
     //Remove your custom view... 
     [self.buttonCustomeCallOut setUserInteractionEnabled:NO]; 
     [self.buttonCustomeCallOut removeFromSuperview]; 

     self.buttonCustomeCallOut=nil; 
    } 
} 
-(void)buttonHandlerCallOut:(UIButton*)sender{ 
    NSLog(@"Annotation Clicked"); 
} 

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

- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent*)event 
{ 
    CGRect rec = self.bounds; 
    BOOL isIn = CGRectContainsPoint(rec, point); 
    if(!isIn) 
    { 
     for (UIView *v in self.subviews) 
     { 
      isIn = CGRectContainsPoint(v.frame, point); 
      if(isIn) 
       break; 
     } 
    } 
    return isIn; 
} 
@end 

место этот код где и хотите создать Custome взывать

- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation { 
    static NSString *identifier = @"CustAnnotation"; 

     CustomeAnnotationView *annotationView = (CustomeAnnotationView *) [self.mapView dequeueReusableAnnotationViewWithIdentifier:identifier]; 
     if (annotationView == nil) { 
      annotationView = [[CustomeAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:identifier]; 
     } 

     annotationView.enabled = YES; 
     annotationView.canShowCallout = NO; 
     annotationView.centerOffset = CGPointMake(0,-10);//-18 

     return annotationView; 
} 
Смежные вопросы