[英]Gesture recogniser not working when added button view to the Label view as subview
[英]Button added as an annotation view subview not working?
我在地圖的didSelect
方法的注釋視圖中添加了一個子視圖,它按預期工作(截圖)。 我在彈出窗口中有一個按鈕,它處於活動狀態並且啟用了用戶交互,但是我沒有得到按鈕操作?
我做了一個視圖調試,看起來按鈕在視圖堆棧的頂部。
func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) {
DispatchQueue.main.async {
view.addSubview(self.popupView)
}
}
此操作方法位於Popupview
@IBAction func actionTapPickup(_ sender: UIButton) {
print("button tapped)
}
您已將actionTapPickup
聲明為@IBAction
。
你真的從接口生成器中設計的 NIB 或故事板實例化了這個視圖嗎? 如果是這樣,請確保您成功連接了@IBAction
? 您是從NIB
實例化此視圖(而不是以編程方式)嗎?
另一方面,如果您以編程方式創建此子視圖,則不會使用@IBAction
限定符,而只是將其標記為@objc
,然后手動添加.touchUpInside
事件的目標:
button.addTarget(self, action: #selector(didTapButton(_:)), for: .touchUpInside)
如果您讓我們知道您是以編程方式還是通過 NIB 實例化此自定義彈出窗口/標注,我們可以更詳細地概述這一點。 (我下面的示例是程序化實現。)
最重要的是,在自定義標注中連接按鈕就像在任何地方連接按鈕一樣。 使用@IBAction
為IB設計的意見,並使用@objc
和addTarget
為程序創建按鈕。
順便說一句,一旦您解決了眼前的問題,值得注意的是,讓自定義標注正常工作存在一些微妙的問題。 位置感知編程指南:創建標注概述了這一點,但不幸的是,示例是在 Objective-C 中的。 無論如何,我們想要的行為是:
為了實現這一點,它在很大程度上可以歸結為兩個不完全明顯的小技巧:
為注釋視圖添加一個hitTest
,其中包括對自定義標注的命中測試。 這是為了確保在您點擊標注時不會取消選擇注釋。
在整個標注后面添加一個按鈕,以便它消耗任何錯過“60 分鍾內接聽”按鈕但仍在標注中的觸摸。
因此:
// let’s assume we have an annotation for our pickup location
class PickupLocationAnnotation: MKPointAnnotation {
let hours: String
init(hours: String) {
self.hours = hours
super.init()
}
}
// let’s have a protocol for the callout to inform view controller that the “pickup” button was tapped
protocol CalloutViewDelegate: class {
func calloutTapped(for annotation: MKAnnotation)
}
// Our callout view class
class CalloutView: UIView {
weak var annotation: MKAnnotation?
weak var delegate: CalloutViewDelegate?
let button: UIButton = {
let button = UIButton(type: .system)
button.translatesAutoresizingMaskIntoConstraints = false
button.setTitle("Tap here to pickup in 60 Mins", for: .normal)
button.addTarget(self, action: #selector(didTapButton(_:)), for: .touchUpInside)
return button
}()
lazy var label: UILabel = {
let label = UILabel()
label.translatesAutoresizingMaskIntoConstraints = false
label.numberOfLines = 0
label.text = (annotation as? PickupLocationAnnotation)?.hours
return label
}()
init(annotation: MKAnnotation?, delegate: CalloutViewDelegate) {
self.annotation = annotation
self.delegate = delegate
super.init(frame: .zero)
configure()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func configure() {
addBackgroundButton(to: self)
addSubview(button)
addSubview(label)
NSLayoutConstraint.activate([
button.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 10),
button.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -10),
button.topAnchor.constraint(equalTo: topAnchor, constant: 10),
button.bottomAnchor.constraint(equalTo: label.topAnchor, constant: -10),
label.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 10),
label.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -10),
label.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -10)
])
layer.cornerRadius = 10
layer.borderColor = UIColor.blue.cgColor
layer.borderWidth = 2
backgroundColor = .white
}
@objc func didTapButton(_ sender: Any) {
if let annotation = annotation {
delegate?.calloutTapped(for: annotation)
}
}
fileprivate func addBackgroundButton(to view: UIView) {
let button = UIButton(type: .custom)
button.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(button)
NSLayoutConstraint.activate([
button.topAnchor.constraint(equalTo: view.topAnchor),
button.bottomAnchor.constraint(equalTo: view.bottomAnchor),
button.leadingAnchor.constraint(equalTo: view.leadingAnchor),
button.trailingAnchor.constraint(equalTo: view.trailingAnchor)
])
}
}
// our annotation view for our pickup annotations
class PickupLocationAnnotationView: MKPinAnnotationView {
weak var calloutView: UIView?
override func prepareForDisplay() {
super.prepareForDisplay()
canShowCallout = false
}
// make sure that hits in callout are recognized as not-deselecting the annotation view
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
if let hitView = super.hitTest(point, with: event) { return hitView }
if let calloutView = calloutView {
let point = convert(point, to: calloutView)
return calloutView.hitTest(point, with: event)
}
return nil
}
// lets move the add callout here, inside the annotation view class,
// so the annotation view can keep track of its callout
func addCallout(delegate: CalloutViewDelegate) {
removeCallout()
let view = CalloutView(annotation: annotation, delegate: delegate)
view.translatesAutoresizingMaskIntoConstraints = false
addSubview(view)
calloutView = view
NSLayoutConstraint.activate([
view.centerXAnchor.constraint(equalTo: centerXAnchor),
view.bottomAnchor.constraint(equalTo: topAnchor, constant: -10)
])
}
func removeCallout() {
calloutView?.removeFromSuperview()
}
}
// random view controller example that adds an annotation
class ViewController: UIViewController {
@IBOutlet weak var mapView: MKMapView!
override func viewDidLoad() {
super.viewDidLoad()
let coordinate = CLLocationCoordinate2D(latitude: 37.332693, longitude: -122.03071)
mapView.camera = MKMapCamera(lookingAtCenter: coordinate, fromDistance: 1_000, pitch: 0, heading: 0)
mapView.register(PickupLocationAnnotationView.self, forAnnotationViewWithReuseIdentifier: MKMapViewDefaultAnnotationViewReuseIdentifier)
let hours = """
Mon to Thu 10am-7pm
Fri 12pm-9pm
Sat 10am-11pm
"""
let annotation = PickupLocationAnnotation(hours: hours)
annotation.coordinate = coordinate
mapView.addAnnotation(annotation)
}
}
// the selecting and deselecting of annotation views
extension ViewController: MKMapViewDelegate {
func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) {
if let view = view as? PickupLocationAnnotationView {
view.addCallout(delegate: self)
}
}
func mapView(_ mapView: MKMapView, didDeselect view: MKAnnotationView) {
if let view = view as? PickupLocationAnnotationView {
view.removeCallout()
}
}
}
// the delegate conformance so view controller can know when the callout button was tapped
extension ViewController: CalloutViewDelegate {
func calloutTapped(for annotation: MKAnnotation) {
print(#function)
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.