Search code examples
swiftuibezierpathcashapelayer

Taps events not getting detected on CAShapeLayer lineWidth?


I have created a circle using Bezier path as well as i created tap events to check whether the layer has been tapped or not, it works fine until i increase the size of lineWidth of CAShapeLayer. By tapping on the lineWidth, sometimes it is detected and sometimes it is not detected.

I searched stackoverflow about the problem which i was having but i am unable to solve it. The problem remains the same, i am unable to detect certain taps on my layer(lineWidth area).

I just want to detect taps on the lineWidth of CAShapeLayer, i have been searching everywhere but couldn't find a proper solution for it. Most of the answers are in outdated languages. I would really appreciate if anyone could give an example to solve my issue. Swift 4.

https://i.sstatic.net/OIU6W.png


let tapRecognizer = UITapGestureRecognizer(target: self, action: #selector(tapDetected(tapRecognizer:)))
    self.addGestureRecognizer(tapRecognizer)

@objc public func tapDetected(tapRecognizer:UITapGestureRecognizer) {
    let tapLocation:CGPoint = tapRecognizer.location(in: self)
    self.hitTest(tapLocation: CGPoint(x: tapLocation.x, y: tapLocation.y))
}


private func hitTest(tapLocation:CGPoint) {
    if layer.path?.contains(tapLocation) == true {
        print("Do something")
    } else {
        print("Nothing Found")
    }
}





Solution

  • The problem is that the line stroke is not really part of the path - is it is just parts of its display. You can convert the path to be an larger path containing the stroke by using some CGPath methods:

    let pathWithLineStroke = UIBezierPath.init(cgPath: path.cgPath.copy(strokingWithWidth: 2.0, lineCap: CGLineCap.butt, lineJoin: .bevel, miterLimit: 1.0));
    

    Of course replace the the width, lineCap, lineJoin, and miterLimit with your actual values.

    I'd recommend doing this earlier in your code, and then just drawing the path that already has the strokes built in, instead of setting those properies on the CALayer.

    Hope that helps. Good luck.