The other way I can think of doing it is track touches and check if they were in the shape with tag, but it seems way to complicated
Okay, but the problem is that you've chosen to do this with layers, and layers do not detect touches at all, so it's hard to see what other choice is open to you. You cannot "cast" a layer into a button; if you wanted buttons, or views that detect taps on themselves, you should have used buttons or views, not layers.
If you use a custom UIView, for example, it can use your shape layer as its layer and implement hit-testing to determine whether a tap falls within the shape layer's hexagon path. Here's an example to get you started:
class HexButton: UIView {
var path: UIBezierPath!
override class func layerClass() -> AnyClass {
return CAShapeLayer.self
}
override init(frame: CGRect) {
super.init(frame:frame)
self.finishInitialization()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder:aDecoder)
self.finishInitialization()
}
func finishInitialization() {
let shape = self.layer as! CAShapeLayer
shape.opacity = 0.5
shape.lineWidth = 2
shape.lineJoin = kCALineJoinMiter
shape.strokeColor = UIColor(hue: 0.786, saturation: 0.79, brightness: 0.53, alpha: 1.0).CGColor
shape.fillColor = UIColor(hue: 0.786, saturation: 0.15, brightness: 0.89, alpha: 1.0).CGColor
let center = CGPoint(x:self.bounds.midX, y: self.bounds.midY)
let radius = self.bounds.width/2.0
let path = UIBezierPath()
path.moveToPoint(CGPointMake(center.x-radius, center.y))
path.addLineToPoint(CGPointMake(center.x-radius/2, center.y-radius))
path.addLineToPoint(CGPointMake(center.x+radius/2, center.y-radius))
path.addLineToPoint(CGPointMake(center.x+radius, center.y))
path.addLineToPoint(CGPointMake(center.x+radius, center.y))
path.addLineToPoint(CGPointMake(center.x+radius/2, center.y+radius))
path.addLineToPoint(CGPointMake(center.x-radius/2, center.y+radius))
path.closePath()
shape.path = path.CGPath
self.path = path
}
override func hitTest(point: CGPoint, withEvent event: UIEvent?) -> UIView? {
return self.path.containsPoint(point) ? self : nil
}
}
If you attach a tap gesture recognizer to that view, you will see that it fires only if the tap is inside the hexagon.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…