【问题标题】: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?如何在地图下方的固定大小组件中显示 MKPinAnnotationView 数据(例如标题、副标题),而不是在图钉上方的弹出窗口中显示?
【发布时间】:2016-06-16 01:44:13
【问题描述】:

我的 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   
    } 
}

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

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

这就是点击地图上任意点后发生的事情:

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

这在Swift 中可以实现吗?

【问题讨论】:

    标签: swift mkmapview mapkit mkannotation mkpinannotationview


    【解决方案1】:

    您可以尝试将 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 等之类的东西时……花几分钟来滚动浏览委托函数。一些委托功能的强大真的令人惊讶。如果您需要其他任何东西,我会在一天的剩余时间里。

    【讨论】:

    • 如何将数据从注解传递到底部的新视图中?
    • 谢谢,看起来很有希望!正如 wtznc 上面所问的那样 - 我怎样才能将数据传递给底部的视图?另外 - 当用户移动地图时,有没有办法隐藏白色方块?目前它一直保持打开状态..
    • 如果需要将数据传递给底部的视图。您可以向函数添加参数。 “func tapToShow(objID:String, randomInt: Int)”。然后,当您调用该函数时,您可以像这样传递数据 "tapToShow("myIDString", 007) 。
    • 我要再添加一件事,而不是让事情复杂化......我希望大声笑。您还可以在情节提要中创建视图。您可以通过将“容器视图”添加到当前的 ViewController 来做到这一点。这将在您当前的视图中“嵌入”一个 ViewController。提供更好的控制和轻松创建所需的布局。
    • 要做到这一点,将一个容器视图拖到你当前的视图控制器中(你想要的大小)。然后连接到当前视图控制器。这将允许您像基本的 UIVIew 示例一样切换隐藏的真/假。接下来创建一个新的 ViewController 类文件。附加到创建容器视图时添加到情节提要的新视图控制器。现在你的代码更干净,更容易管理……当新设备发布时,也更有未来的证明。编码愉快。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-15
    相关资源
    最近更新 更多