【问题标题】:Swift - Making MapView callout annotation visible when pin annotation clicked by UserSwift - 当用户单击引脚注释时,使 MapView 标注注释可见
【发布时间】:2017-02-22 18:37:38
【问题描述】:

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

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

我的问题有两个:

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

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

Mapview屏幕调整顺序:

【问题讨论】:

    标签: ios swift mkmapview mapkit mkmapviewdelegate


    【解决方案1】:

    理论上,你可以获取annotation view的frame并检查它是否离map view的边缘太近:

    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")
        }
    }
    

    它适用于我对其进行的基本测试,但由于它是一个 hack,因此显然会出现极端情况。

    【讨论】:

    • 感谢您抽出宝贵时间回复。我很感激。
    【解决方案2】:

    我想出的是以下内容:

     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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-10-17
      • 1970-01-01
      • 1970-01-01
      • 2011-09-02
      • 1970-01-01
      • 1970-01-01
      • 2015-01-22
      • 1970-01-01
      相关资源
      最近更新 更多