Resize annotationview frame to custom shape

98 Views Asked by At

I'm developing an application that uses custom annotationview pins on a map. The head of the pin is a button that dynamically resizes. I'm pretty new to swift and noticed that the button only registers if it is on top of the annotationviews frame, therefore I set the frame to be large enough to always contain the uibutton.

The problem: when I have multiple pins on the map the large frame overlaps other pinheads and interferes with tapping on them. I want to slim the frame as small as possible so it doesn't interfere with tapping on other pins. The frame could certainly be slimmed down by just making the frame rectangle smaller, but I'm wondering if I could do better.

My questions is: is there a way to modify the frame shape of the annotation view so it is the same shape as the pin, instead of a rectangle?

  • I thought to use bezierpaths to achieve this but haven't been able to figure out how

Here is an image of the custom pin

-the blue is the frame and the red is a bezier path which I tried to set as the frame but just got drawn over

1

There are 1 best solutions below

3
Leo Chen On

I got a test for custom size button,it is only triggered when click green part.

class TestButton: UIButton {
    var path:UIBezierPath!
    var drawLayer:CAShapeLayer!
    
    override init(frame: CGRect) {
        super.init(frame: frame)
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    override func draw(_ rect: CGRect) {
        path = UIBezierPath()
        path.move(to: CGPoint(x: 60, y: 100))
        path.addLine(to: CGPoint(x: 0, y: 100))
        path.addArc(withCenter: CGPoint(x: 100, y: 100), radius: 100, startAngle: .pi, endAngle: .pi*1.5, clockwise: true)
        path.addLine(to: CGPoint(x: 100, y: 60))
        path.addArc(withCenter: CGPoint(x: 100, y: 100), radius: 40, startAngle: .pi*1.5, endAngle: .pi, clockwise: false)
        path.close()
        
        drawLayer = CAShapeLayer.init()
        drawLayer.path = self.path.cgPath
        drawLayer.fillColor = UIColor.green.cgColor
        self.layer.addSublayer(self.drawLayer)
    }
    
    override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
        if self.path.contains(point) {
            return true
        } else {
            return false
        }
    }
    
    public override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
        print(point)
        let tmp=super.hitTest(point, with: event)
        print(tmp)
        return tmp
    }
}


class vc_UnitTest: UIViewController {

    @IBAction func openLoginHome(_ sender: Any) {
        let bbb = TestButton.init(frame: CGRect.init(x: 50, y: 400, width: 150, height: 150))
        bbb.backgroundColor = .red
        self.view.addSubview(bbb)
    }
}

enter image description here