如何在地图下方的 fixed-size 组件中显示 MKPinAnnotationView 数据(例如标题、副标题)而不是图钉上方的弹出窗口?

How can I display a MKPinAnnotationView data (e.g. title, subtitle) in a fixed-size component below the map instead of the popup above the pin?

我的 swift ios 应用程序中有一张地图,上面全是标记。因此我决定使用从这里获取的标记聚类:https://github.com/ribl/FBAnnotationClusteringSwift

在我的应用程序中实现它后,我看到了图钉和簇,这很酷。

我是这样做的 - 首先我调用我的网络服务并获取每个引脚的所有数据并将其放入数组中:

func fetchRequests(radius: Double, lat: Double, lon: Double, completionHandler: (() -> Void)?){
    Alamofire.request(.GET, "http://mywebservice.com/fetchdata", parameters: ["param": "1"])
        .responseJSON { response in
            switch response.result {
            case .Success:

                self.array.removeAll()
                if let jsonData = response.result.value as? [[String: AnyObject]] {
                    for requestJSON in jsonData {
                        if let request = SingleRequest.fromJSON(JSON(requestJSON)){

                            let pinOne = FBAnnotation()
                            pinOne.coordinate = CLLocationCoordinate2D(latitude: request.latitude, longitude: request.longitude)
                            pinOne.title = request.title
                            pinOne.subtitle = request.discipline
                            self.array.append(pinOne)
                        }
                    }
                }
                self.clusteringManager.setAnnotations(self.array)
                completionHandler!()

                case .Failure(let error):
                print("SWITCH ERROR")
                print(error)
            }

    }
}

然后我实际上是从上面调用函数并执行:

let annotationArray = self?.clusteringManager.clusteredAnnotationsWithinMapRect(self!.mapView.visibleMapRect, withZoomScale:scale)
self?.clusteringManager.displayAnnotations(annotationArray!, onMapView:(self?.mapView)!)

最后,我将数据放在地图上,同时检查每个图钉是簇还是普通图钉:

func mapView(mapView: MKMapView!, viewForAnnotation annotation: MKAnnotation!) -> MKAnnotationView! {
    var reuseId = ""
    if annotation.isKindOfClass(FBAnnotationCluster) {
        reuseId = "Cluster"
        var clusterView = mapView.dequeueReusableAnnotationViewWithIdentifier(reuseId)
        clusterView = FBAnnotationClusterView(annotation: annotation, reuseIdentifier: reuseId, options: nil)

        return clusterView
    } else {
        reuseId = "Pin"
        var pinView = mapView.dequeueReusableAnnotationViewWithIdentifier(reuseId) as? MKPinAnnotationView
        pinView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
        pinView!.calloutOffset = CGPoint(x: -5, y: 5)
        pinView!.canShowCallout = true
        pinView!.rightCalloutAccessoryView = UIButton(type: .DetailDisclosure) as UIView

        return pinView   
    } 
}

到目前为止一切顺利。它按预期工作,在单击每个图钉后,我看到它上面的弹出窗口带有 titlesubtitle。但我想达到不同的效果。

当用户点击图钉时 - 而不是其上方的弹出窗口 - 地图下方会出现一些方形组件。我正在寻找一些类似的解决方案作为示例,我在名为 Periscope 的应用程序中找到了它 - 这是他们的地图在用户点击任何事件之前的样子:

这是点击地图上的任意点后立即发生的情况:

当然,一旦用户滚动地图,这个组件就会消失。

Swift 中可以实现吗?

您可以尝试将 UITapGestureRecognizer 添加到您的 MKMapView。然后对于操作,创建一个将在底部显示视图的函数。

在 viewDidLoad() 中添加了 GestureRecognizer:

let showTap : UIGestureRecognizer = UITapGestureRecognizer(target: self, action: "tapShowView:")
    myMapView.addGestureRecognizer(showTap)

那么你的函数可能是这样的。

 func tapShowView(sender:UIGestureRecognizer) {

   //Animate UIView in......

   //Or just add your UIView.
    let viewHeight = CGFloat(80)
    let bottomView = UIView(frame: CGRect(x: 0, y: self.view.frame.height - viewHeight, width: self.view.frame.width, height: viewHeight))
        bottomView.backgroundColor = .whiteColor()

   //add buttons, navbar etc....

    self.myMapView.addSubview(bottomView)
    //OR if you add it in viewDidload and set to bottomView.hidden = true
    bottomView.hidden = false

}

请忽略任何语法错误,我没有坐在 Xcode 上。但这应该会给你一个推动力。如果你有任何问题,我会在几个小时后(凌晨 1 点 31 分)醒来时回来。祝你编码愉快。

编辑:

我想我错过了你的问题.....如果你想在用户触摸注释时显示 "BottomView"。您可以从 MapViewDelegate 方法调用 "tapShowView" 方法。

    func mapView(mapView: MKMapView, didSelectAnnotationView view: MKAnnotationView) {

    if view.annotation!.isKindOfClass(FBAnnotationCluster) {

        print("cluster selected")

    } else {

        print("single pin selected")
        //Call method here to display BottomView.
        self.tapShowView() //Edit tapShowView to remove sender
    }

}

然后为了防止在您触摸此委托方法中的注释时显示任何标注..

   func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {

添加:

 annotationView?.canShowCallout = true   

编辑 2: 如果您需要在用户滚动地图等时切换视图。您可以在区域中做到这一点,但确实更改了委托方法。

 func mapView(mapView: MKMapView, regionDidChangeAnimated animated: Bool){
  //Just toggle the hidden property of the view.
  BottomView.hidden = true
 }

我建议您好好看看 MKMapView 委托函数。你可以用它们做很多很酷的事情。任何时候你添加类似 UITableView/UICollectionView/MKMapView 等的东西...花几分钟滚动浏览委托函数。某些委托函数的强大程度真是令人惊叹。如果您需要其他任何东西,我会在当天剩下的时间左右。