2015-12-21 3 views
1

Я пытаюсь центрировать MKMapView после того, как была выбрана аннотация. Я также включил canShowCallout, но кажется, что iOS сначала отображает выносок (который сдвинут, когда он не поместится на экране), а затем карта перемещается, в результате чего выноска не отображается полностью на экране.Центр MKMapView ПЕРЕД показа показанием

incorrect callout position

Как центрировать карту до положения выноски в визуализируется и отображается?

+0

Вы пробовали настройку 'MKCoordinateRegion' с широтой и долготой устанавливаются таким же, как контактные, и пролет установлен независимо от текущей пяди, а затем установив свойство «center» области на местоположение булавки? – GlennRay

+0

@GlennRay это будет просто центрировать карту на штырьке, а также только после отображения выноски, если я правильно пойму. – Ch1llb4y

+0

Глядя на другие вопросы, подобные этому очень быстро, появляются два решения. Во-первых, вы можете использовать диспетчер, чтобы задержать появление выноски в течение нескольких секунд, дав центру время карты. Или вы можете иметь центр карты на месте x%/y% от места, где на самом деле находится контакт, чтобы уступить место выноску. – GlennRay

ответ

2

Я хотел сделать то же самое и закончил делать следующее.

Предостережение перед тем, как я начну: я знаю, что решение довольно уродливое! ... но эй, это работает.

Примечание: Я нацеливание IOS 9, но он должен работать на предыдущие версии прошивки:

Хорошо, здесь мы идем:

  • Во-первых, создать новое свойство в контроллере представления, например, : @property(nonatomic, assign, getter=isPinCenteringOngoing) BOOL pinCenteringOngoing;
  • в mapView:viewForAnnotation: установить canShowCallout в NO для 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]; 
         }); 
        }); 
    } 
    

Чтобы завершить мой ответ, здесь это текстовое объяснение того, что я делаю в приведенном выше коде и почему я это делаю:

  • То, что я хочу, это аннотация, которая будет центрирована на экране, и выносок, который будет центрирован над ним.
  • Что я получаю по умолчанию является:
    • При выборе аннотации, карта открывает выноски, и при необходимости корректирует карту таким образом, выноска помещается на экране. Ни в коем случае эта стандартная реализация не гарантирует, что выноска «центрирована» над аннотацией.
    • Поцентрирование карты с помощью setCenterCoordinate :, аннотация направлена ​​по центру.
    • Теперь два предыдущих совмещенных точки могут привести к тому, что выноска будет «обрезана», поскольку аннотация центрирована на карте, но выноска не центрируется над аннотацией.
  • Чтобы это исправить, я следующее:
    • первым отключить выноски, который будет отображаться по умолчанию, установив canShowCallout ни к чему для каждого annotationView
    • , когда пользователь выбирает аннотацию, я первый центрировать карту
    • затем я позволил выноске быть показана, установкой canShowCallout ДА для выбранной аннотации
    • я тогда отменить выбор, а затем снова выберите аннотацию, так выноска фактически отображается
    • для того, чтобы выноски быть правильно по центру над аннотацией, мне нужно сделать Deselecting/выбор несколько запаздывает, так что карта центрирование может завершить

Я надеюсь, что мой ответ может оказаться полезным.

+0

Как нам создать @property в swift? На самом деле, как мы можем достичь вышеуказанного решения с помощью swift? –

+0

@LohithKorupolu просто поместил 'var' в начало вашего класса, так как' var pinCenteringOngoing = false' – Thermometer

0

Здесь на другое решение:

  1. Создать новую булево свойство var selectFirstAnnotation = false в контроллере

  2. Установите его в истинный, прежде чем к центру аннотацию

  3. Добавить это в regionDidChangeAnimated.

    func mapView(_ mapView: MKMapView, regionDidChangeAnimated animated: Bool) { 
         if selectFirstAnnotation == true { 
          if let annotation = mapView.annotations.first(where: { !($0 is MKUserLocation) }) { 
          mapView.selectAnnotation(annotation, animated: true) 
          selectFirstAnnotation = false 
        }}} 
    

прекрасно работает для моего поведения

Смежные вопросы