如何将 MGLAnnotationView 设置为 popover 的 sourceView
How to set MGLAnnotationView as sourceView for popover
我想做的是显示一个以注释为源的弹出窗口view/anchor
通过使用委托函数didSelect annotationView我应该可以实现这个,但它似乎根本运行。
现在我只是通过 didSelect annotation 显示我的弹出窗口并将 sourceView 设置为导航栏,只是为了在某处显示它...
仅供参考:
我已经在项目中实现了 Mapbox SDK。
我使用 MapKit 执行相同的任务没有问题。
有人知道我可以做些什么来实现这个目标吗?
下面的代码片段:
import UIKit
import Mapbox
class ViewController: UIViewController, MGLMapViewDelegate, UIPopoverPresentationControllerDelegate {
@IBOutlet var theMap: MGLMapView!
override func viewDidLoad() {
super.viewDidLoad()
theMap.delegate = self
let point = MGLPointAnnotation()
point.coordinate = CLLocationCoordinate2D(latitude: 55.6, longitude: 13.0)
point.title = "Some place"
point.subtitle = "Malmö, Sweden"
theMap.addAnnotation(point)
}
func mapView(_ mapView: MGLMapView, didSelect annotationView: MGLAnnotationView) {
print("annotation view: ", annotationView)
// this method doesn't seem to get called at all...
// but ideally this is the place to present the popover.
}
func mapView(_ mapView: MGLMapView, didSelect annotation: MGLAnnotation) {
print("annotation: ", annotation)
// present the popover
presentPopover()
}
func presentPopover(){
let popover = storyboard?.instantiateViewController(withIdentifier: "MyCalloutVC") as! MyCallout
popover.modalPresentationStyle = UIModalPresentationStyle.popover
popover.popoverPresentationController?.backgroundColor = UIColor.white
popover.popoverPresentationController?.delegate = self
// I would like to set the source anchor to the selected annotation view.
popover.popoverPresentationController?.sourceView = UINavigationBar() // set to nav bar for now...
popover.popoverPresentationController?.permittedArrowDirections = .any
// popover size set in MyCallout
self.present(popover, animated: true)
}
}
没有调用该函数,因为没有可供选择的注释视图。
这意味着您只需添加点注释而不是注释视图。因此,您必须这样做:
添加注释时,将调用 func mapView(_ mapView: MGLMapView, viewFor annotation: MGLAnnotation) -> MGLAnnotationView? {}
,您可以在其中定义注释视图 return。然后将调用 did selected 函数。查看示例代码:https://www.mapbox.com/ios-sdk/examples/annotation-views/
import Mapbox
// Example view controller
class ViewController: UIViewController, MGLMapViewDelegate {
override func viewDidLoad() {
super.viewDidLoad()
let mapView = MGLMapView(frame: view.bounds)
mapView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
mapView.styleURL = MGLStyle.darkStyleURL(withVersion: 9)
mapView.tintColor = .lightGray
mapView.centerCoordinate = CLLocationCoordinate2D(latitude: 0, longitude: 66)
mapView.zoomLevel = 2
mapView.delegate = self
view.addSubview(mapView)
// Specify coordinates for our annotations.
let coordinates = [
CLLocationCoordinate2D(latitude: 0, longitude: 33),
CLLocationCoordinate2D(latitude: 0, longitude: 66),
CLLocationCoordinate2D(latitude: 0, longitude: 99),
]
// Fill an array with point annotations and add it to the map.
var pointAnnotations = [MGLPointAnnotation]()
for coordinate in coordinates {
let point = MGLPointAnnotation()
point.coordinate = coordinate
point.title = "\(coordinate.latitude), \(coordinate.longitude)"
pointAnnotations.append(point)
}
mapView.addAnnotations(pointAnnotations)
}
// MARK: - MGLMapViewDelegate methods
// This delegate method is where you tell the map to load a view for a specific annotation. To load a static MGLAnnotationImage, you would use `-mapView:imageForAnnotation:`.
func mapView(_ mapView: MGLMapView, viewFor annotation: MGLAnnotation) -> MGLAnnotationView? {
// This example is only concerned with point annotations.
guard annotation is MGLPointAnnotation else {
return nil
}
// Use the point annotation’s longitude value (as a string) as the reuse identifier for its view.
let reuseIdentifier = "\(annotation.coordinate.longitude)"
// For better performance, always try to reuse existing annotations.
var annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: reuseIdentifier)
// If there’s no reusable annotation view available, initialize a new one.
if annotationView == nil {
annotationView = CustomAnnotationView(reuseIdentifier: reuseIdentifier)
annotationView!.frame = CGRect(x: 0, y: 0, width: 40, height: 40)
// Set the annotation view’s background color to a value determined by its longitude.
let hue = CGFloat(annotation.coordinate.longitude) / 100
annotationView!.backgroundColor = UIColor(hue: hue, saturation: 0.5, brightness: 1, alpha: 1)
}
return annotationView
}
func mapView(_ mapView: MGLMapView, annotationCanShowCallout annotation: MGLAnnotation) -> Bool {
return true
}
}
//
// MGLAnnotationView subclass
class CustomAnnotationView: MGLAnnotationView {
override func layoutSubviews() {
super.layoutSubviews()
// Force the annotation view to maintain a constant size when the map is tilted.
scalesWithViewingDistance = false
// Use CALayer’s corner radius to turn this view into a circle.
layer.cornerRadius = frame.width / 2
layer.borderWidth = 2
layer.borderColor = UIColor.white.cgColor
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Animate the border width in/out, creating an iris effect.
let animation = CABasicAnimation(keyPath: "borderWidth")
animation.duration = 0.1
layer.borderWidth = selected ? frame.width / 4 : 2
layer.add(animation, forKey: "borderWidth")
}
}
我想做的是显示一个以注释为源的弹出窗口view/anchor
通过使用委托函数didSelect annotationView我应该可以实现这个,但它似乎根本运行。 现在我只是通过 didSelect annotation 显示我的弹出窗口并将 sourceView 设置为导航栏,只是为了在某处显示它...
仅供参考: 我已经在项目中实现了 Mapbox SDK。 我使用 MapKit 执行相同的任务没有问题。
有人知道我可以做些什么来实现这个目标吗?
下面的代码片段:
import UIKit
import Mapbox
class ViewController: UIViewController, MGLMapViewDelegate, UIPopoverPresentationControllerDelegate {
@IBOutlet var theMap: MGLMapView!
override func viewDidLoad() {
super.viewDidLoad()
theMap.delegate = self
let point = MGLPointAnnotation()
point.coordinate = CLLocationCoordinate2D(latitude: 55.6, longitude: 13.0)
point.title = "Some place"
point.subtitle = "Malmö, Sweden"
theMap.addAnnotation(point)
}
func mapView(_ mapView: MGLMapView, didSelect annotationView: MGLAnnotationView) {
print("annotation view: ", annotationView)
// this method doesn't seem to get called at all...
// but ideally this is the place to present the popover.
}
func mapView(_ mapView: MGLMapView, didSelect annotation: MGLAnnotation) {
print("annotation: ", annotation)
// present the popover
presentPopover()
}
func presentPopover(){
let popover = storyboard?.instantiateViewController(withIdentifier: "MyCalloutVC") as! MyCallout
popover.modalPresentationStyle = UIModalPresentationStyle.popover
popover.popoverPresentationController?.backgroundColor = UIColor.white
popover.popoverPresentationController?.delegate = self
// I would like to set the source anchor to the selected annotation view.
popover.popoverPresentationController?.sourceView = UINavigationBar() // set to nav bar for now...
popover.popoverPresentationController?.permittedArrowDirections = .any
// popover size set in MyCallout
self.present(popover, animated: true)
}
}
没有调用该函数,因为没有可供选择的注释视图。
这意味着您只需添加点注释而不是注释视图。因此,您必须这样做:
添加注释时,将调用 func mapView(_ mapView: MGLMapView, viewFor annotation: MGLAnnotation) -> MGLAnnotationView? {}
,您可以在其中定义注释视图 return。然后将调用 did selected 函数。查看示例代码:https://www.mapbox.com/ios-sdk/examples/annotation-views/
import Mapbox
// Example view controller
class ViewController: UIViewController, MGLMapViewDelegate {
override func viewDidLoad() {
super.viewDidLoad()
let mapView = MGLMapView(frame: view.bounds)
mapView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
mapView.styleURL = MGLStyle.darkStyleURL(withVersion: 9)
mapView.tintColor = .lightGray
mapView.centerCoordinate = CLLocationCoordinate2D(latitude: 0, longitude: 66)
mapView.zoomLevel = 2
mapView.delegate = self
view.addSubview(mapView)
// Specify coordinates for our annotations.
let coordinates = [
CLLocationCoordinate2D(latitude: 0, longitude: 33),
CLLocationCoordinate2D(latitude: 0, longitude: 66),
CLLocationCoordinate2D(latitude: 0, longitude: 99),
]
// Fill an array with point annotations and add it to the map.
var pointAnnotations = [MGLPointAnnotation]()
for coordinate in coordinates {
let point = MGLPointAnnotation()
point.coordinate = coordinate
point.title = "\(coordinate.latitude), \(coordinate.longitude)"
pointAnnotations.append(point)
}
mapView.addAnnotations(pointAnnotations)
}
// MARK: - MGLMapViewDelegate methods
// This delegate method is where you tell the map to load a view for a specific annotation. To load a static MGLAnnotationImage, you would use `-mapView:imageForAnnotation:`.
func mapView(_ mapView: MGLMapView, viewFor annotation: MGLAnnotation) -> MGLAnnotationView? {
// This example is only concerned with point annotations.
guard annotation is MGLPointAnnotation else {
return nil
}
// Use the point annotation’s longitude value (as a string) as the reuse identifier for its view.
let reuseIdentifier = "\(annotation.coordinate.longitude)"
// For better performance, always try to reuse existing annotations.
var annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: reuseIdentifier)
// If there’s no reusable annotation view available, initialize a new one.
if annotationView == nil {
annotationView = CustomAnnotationView(reuseIdentifier: reuseIdentifier)
annotationView!.frame = CGRect(x: 0, y: 0, width: 40, height: 40)
// Set the annotation view’s background color to a value determined by its longitude.
let hue = CGFloat(annotation.coordinate.longitude) / 100
annotationView!.backgroundColor = UIColor(hue: hue, saturation: 0.5, brightness: 1, alpha: 1)
}
return annotationView
}
func mapView(_ mapView: MGLMapView, annotationCanShowCallout annotation: MGLAnnotation) -> Bool {
return true
}
}
//
// MGLAnnotationView subclass
class CustomAnnotationView: MGLAnnotationView {
override func layoutSubviews() {
super.layoutSubviews()
// Force the annotation view to maintain a constant size when the map is tilted.
scalesWithViewingDistance = false
// Use CALayer’s corner radius to turn this view into a circle.
layer.cornerRadius = frame.width / 2
layer.borderWidth = 2
layer.borderColor = UIColor.white.cgColor
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Animate the border width in/out, creating an iris effect.
let animation = CABasicAnimation(keyPath: "borderWidth")
animation.duration = 0.1
layer.borderWidth = selected ? frame.width / 4 : 2
layer.add(animation, forKey: "borderWidth")
}
}