自定义MKAnnotationView仅底部响应点击,mapView:didSelect方法无法稳定触发
问题根因
iOS 默认不会将点击事件传递到超出父视图 bounds 范围的子视图区域,你的代码存在两处核心问题导致点击失效:
- 你给
containerView设置了x: -40, y: -70的负坐标,而MKAnnotationView本身的 bounds 只有 70x70 大小,导致containerView90% 以上的区域都在父视图的 bounds 之外,无法响应点击 - 所有子视图都开启了
isUserInteractionEnabled = true,会拦截点击事件,导致MKMapView的didSelect代理无法正常触发
解决方案
调整视图布局逻辑,将所有子视图放在 MKAnnotationView 的 bounds 范围内,通过 centerOffset 属性调整标注相对于坐标点的偏移位置,不要通过给子视图设置负坐标实现偏移效果。
具体代码修改
1. 修改 mapView(_:viewFor:) 方法
删掉手动给 annotationView 赋值 frame 的代码:
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? { guard !annotation.isKind(of: MKUserLocation.self) else { return nil } var annotationView: MKAnnotationView! var annotationIdentifier: String! if annotation.isKind(of: GroupUserAnnotation.self) { annotationIdentifier = "groupUser" annotationView = GroupUserAnnotationView(annotation: annotation as! GroupUserAnnotation, reuseIdentifier: annotationIdentifier) // 删掉下面这行错误代码 // annotationView.frame = (annotationView as! GroupUserAnnotationView).containerView.frame } else { annotationIdentifier = "marker" annotationView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: annotationIdentifier) } return annotationView }
2. 修改 GroupUserAnnotationView 代码
class GroupUserAnnotationView: MKAnnotationView { public lazy var containerView: UIView = { // 移除负坐标,origin 改为 0,0 let view = UIView(frame: CGRect(x: 0, y: 0, width: 70, height: 70)) view.backgroundColor = .accentColor view.layer.cornerRadius = view.frame.width / 2 // 关闭不必要的用户交互,避免拦截点击 view.isUserInteractionEnabled = false return view }() public lazy var imageView: UIImageView = { let imageView = UIImageView() imageView.translatesAutoresizingMaskIntoConstraints = false imageView.image = (annotation as! GroupUserAnnotation).image! imageView.clipsToBounds = true // 关闭用户交互 imageView.isUserInteractionEnabled = false return imageView }() public lazy var bottomCornerView: UIView = { let view = UIView() view.translatesAutoresizingMaskIntoConstraints = false view.backgroundColor = .accentColor view.layer.cornerRadius = 4.0 // 关闭用户交互 view.isUserInteractionEnabled = false return view }() override init(annotation: MKAnnotation?, reuseIdentifier: String?) { super.init(annotation: annotation as! GroupUserAnnotation, reuseIdentifier: reuseIdentifier) setupView() // 新增:设置 annotationView 大小,包含底部尖角的总高度 bounds = CGRect(x: 0, y: 0, width: 70, height: 74) // 新增:设置偏移,让底部尖角对准坐标点 centerOffset = CGPoint(x: 0, y: -bounds.height / 2) } // 其余原有代码保持不变 }
修改完成后整个标注的所有区域都可以正常响应点击,didSelect 代理会正常触发。
内容的提问来源于stack exchange,提问作者goatofanerd
相关产品推荐
相关产品推荐

