2017-02-22 2 views
-1

Обратите внимание на связанное изображение (внизу, ниже)Swift - Создание MapView выноска аннотация видна при штырьковой аннотации щелкнула Пользователь

Когда пользователь перемещает экран карты туда, где штифт заканчивается у края экрана и затем выбирает эту булавку-аннотацию, метод Apple затем слегка перемещает экран карты в направлении к центру экрана, чтобы можно было видеть вырезанную аннотацию.

Мой вопрос имеет два аспекта:

I. Какой метод Apple, называется, чтобы сделать эту настройку экрана?

II. Каким будет самый умный способ реализовать ту же функциональность в методе mapView didSelect, если было реализовано расширение MKMapViewDelegate?

MAPview последовательность регулировка экрана:

ответ

0

Теоретически, вы можете получить кадр пояснительных и проверить, если это слишком близко к краям вида карты:

func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) { 
    // if view.frame is too close to the edges of the MKMapView, triggered your desired method 
} 

На практике это ненадежно, потому что это также зависит от пузыря выноски аннотации. Нам нужен разный порог для критериев «слишком близко к краям» в зависимости от размера пузыря выноски, для которого нет простого способа сделать.

Это немного взломанный: при настройке экрана вызывается метод regionWillChangeAnimated. Если он запускается в течение доли секунды, нажав на аннотации, есть хороший шанс, что это было вызвано пользователем врезки на аннотации:

weak var tappedAnnotationView: MKAnnotationView? 

func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) { 
    self.tappedAnnotationView = view // this property will only be non-nil for 0.1 seconds 
    DispatchQueue.global().asyncAfter(deadline: .now() + 0.1) { 
     self.tappedAnnotationView = nil 
    } 
} 

func mapView(_ mapView: MKMapView, regionWillChangeAnimated animated: Bool) { 
    if self.tappedAnnotationView != nil { 
     print("map adjusted due to tap on an annotation view") 
    } 
} 

Он работает для основных тестов я бросил на нее, но, очевидно, есть будут крайние случаи, когда он сломается, так как это взломать.

+0

Спасибо, что нашли время ответить. Я ценю это. –

0

То, что я придумал следующий:

func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) { 

    // Get Coordinate for Selected Map Pin 
    let selectedPinCoordinate = (view.annotation?.coordinate)! 

    // Determine (X,Y) coordinates for Selected Map Pin on view (mapView) 
    let SelectedPinMapPoint = mapView.convert(selectedPinCoordinate, toPointTo: mapView) 

    // Determine (X,Y) coordinate for center point of view (mapView) 
    let mapCenterMapPoint = mapView.convert(mapView.centerCoordinate, toPointTo: mapView) 

    // Define an inner view within the existing view frame. Any Selected Map Pin outside 
    // bounds of inner view is deemed to be too close to the edge of the map for the callout 
    // to be fully viewable by the user 
    let innerRectFrameMinX = mapView.frame.maxX * 0.15 
    let innerRectFrameMaxX = mapView.frame.maxX * 0.85 
    let innerRectFrameMinY = mapView.frame.maxY * 0.30 
    let innerRectFrameMaxY = mapView.frame.maxY * 0.85 

    // Create a variable which will serve as the new center (X,Y) coordinate 
    var newCenter = CGPoint() 

    // Default new center (X,Y) coordinate to current view (X,Y) coordinate 
    newCenter.x = mapCenterMapPoint.x 
    newCenter.y = mapCenterMapPoint.y 


    // Determine if x coordinate of Selected Map Pin is outside bounds. If so, 
    // set a new center x coordinate so callout can be clearly seen by the user 
    switch (SelectedPinMapPoint.x) { 

    case _ where (SelectedPinMapPoint.x < innerRectFrameMinX): 
     newCenter.x = mapView.frame.midX - (innerRectFrameMinX - SelectedPinMapPoint.x) 

    case _ where (SelectedPinMapPoint.x > innerRectFrameMaxX): 
     newCenter.x = mapView.frame.midX + (SelectedPinMapPoint.x - innerRectFrameMaxX) 

    default: break 

    } 

    // Determine if y coordinate of Selected Map Pin is outside bounds. If so, 
    // set a new center y coordinate so callout can be clearly seen by the user 
    switch (SelectedPinMapPoint.y) { 

    case _ where (SelectedPinMapPoint.y < innerRectFrameMinY): 
     newCenter.y = mapView.frame.midY - (innerRectFrameMinY - SelectedPinMapPoint.y) 

    case _ where (SelectedPinMapPoint.y > innerRectFrameMaxY): 
     newCenter.y = mapView.frame.midY + (SelectedPinMapPoint.y - innerRectFrameMaxY) 

    default: break 

    } 

    // Convert new map Center (X,Y) coordinate to map coordinate 
    let newCenterCoordinate = mapView.convert(newCenter, toCoordinateFrom: nil) 

    // Set new center as center for map view 
    mapView.setCenter(newCenterCoordinate, animated: true) 

} 

я связан грубый графический эскиз моей концепции на то, что пользу он может предоставить. Rough Graphical Sketch

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