Swift - 当用户点击引脚注释时,可以看到MapView标注注释

时间:2017-02-22 18:37:39

标签: ios swift mkmapview mapkit mkmapviewdelegate

请观察链接的图片(下方,下方)

当用户将地图屏幕移动到靠近屏幕边缘的引脚位置然后选择该引脚注释时,Apple方法然后将地图屏幕稍微移向屏幕中心,以便引脚注释标注是可见的。

我的问题有两个:

予。调用什么Apple方法进行屏幕调整?

II。如果实现了MKMapViewDelegate扩展,那么在mapView didSelect视图方法中实现相同功能的最聪明方法是什么?

Mapview屏幕调整顺序:

2 个答案:

答案 0 :(得分:0)

理论上,您可以获取注释视图的框架并检查它是否太靠近地图视图的边缘:

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

在实践中,这是不可靠的,因为它还取决于注释视图的标注气泡。根据标注气泡的大小,我们需要一个“太靠近边缘”标准的不同阈值,对此没有简单的方法。

这有点hacky:当屏幕调整时,将调用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")
    }
}

它适用于我投入的基本测试,但显然会出现极端情况,因为它是黑客攻击。

答案 1 :(得分: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