0

I'm currently trying to create a button that has the shape of a hexagon but the button still reacts to taps that are outside of its shape.
I successfully created the shape by overriding the func draw(_ rect: CGRect) (see below) but unfortunately I can't figure out how to restrict the tappable area to the shape.
I also tried to set clipsToBound to true but that didn't help either.

override func draw(_ rect: CGRect) {

        let radiusOuterCircle: CGFloat = self.frame.width / 2
        let centerXY = self.frame.width / 2
        let initialPoint = CGPoint(x: 0, y: centerXY)

        let shapePath = UIBezierPath()
        shapePath.move(to: initialPoint)

        let secondPoint = CGPoint(x: radiusOuterCircle / 2, y: abs(tan(CGFloat.pi / 3) * (radiusOuterCircle / 2)) + centerXY)
        let thirdPoint = CGPoint(x: radiusOuterCircle / 2 * 3, y: secondPoint.y)
        let fourthPoint = CGPoint(x: radiusOuterCircle * 2, y: centerXY)
        let fifthPoint = CGPoint(x: thirdPoint.x, y: centerXY - abs(tan(CGFloat.pi / 3) * (radiusOuterCircle / 2)))
        let sixthPoint = CGPoint(x: centerXY / 2, y: fifthPoint.y)

        shapePath.addLine(to: secondPoint)
        shapePath.addLine(to: thirdPoint)
        shapePath.addLine(to: fourthPoint)
        shapePath.addLine(to: fifthPoint)
        shapePath.addLine(to: sixthPoint)
        shapePath.close()

        UIColor(red: 247/255, green: 204/255, blue: 47/255, alpha: 1.0).set()
        shapePath.fill()
    }

Thank you very much :)

Lennart P.
  • 316
  • 1
  • 6
  • 20
  • Maybe with https://stackoverflow.com/questions/7374937/uibutton-touchupinside-touch-location you'll get the position of the tap and check if it's "valid" or not, inside your path. – Larme Apr 03 '20 at 16:32
  • do you know how I could detect the position of the button inside of Custom Button class? – Lennart P. Apr 03 '20 at 18:13

1 Answers1

0

https://stackoverflow.com/a/36877464/7615046
This actually is the answer to my problem.

Below you can fing my updated code (Swift 5.1) as the other code is not up to date anymore:

override func awakeFromNib() {
        addTarget(self, action: #selector(touchDown(button:event:)), for: .touchDown)
    }

override func draw(_ rect: CGRect) {

        let radiusOuterCircle: CGFloat = self.frame.width / 2
        let centerXY = self.frame.width / 2
        let initialPoint = CGPoint(x: 0, y: centerXY)

        shapePath.move(to: initialPoint)

        let secondPoint = CGPoint(x: radiusOuterCircle / 2, y: abs(tan(CGFloat.pi / 3) * (radiusOuterCircle / 2)) + centerXY)
        let thirdPoint = CGPoint(x: radiusOuterCircle / 2 * 3, y: secondPoint.y)
        let fourthPoint = CGPoint(x: radiusOuterCircle * 2, y: centerXY)
        let fifthPoint = CGPoint(x: thirdPoint.x, y: centerXY - abs(tan(CGFloat.pi / 3) * (radiusOuterCircle / 2)))
        let sixthPoint = CGPoint(x: centerXY / 2, y: fifthPoint.y)

        shapePath.addLine(to: secondPoint)
        shapePath.addLine(to: thirdPoint)
        shapePath.addLine(to: fourthPoint)
        shapePath.addLine(to: fifthPoint)
        shapePath.addLine(to: sixthPoint)
        shapePath.close()

        UIColor(red: 247/255, green: 204/255, blue: 47/255, alpha: 1.0).set()
        shapePath.fill()
    }

@objc func touchDown(button: HexagonButton, event: UIEvent) {
        if let touch = event.touches(for: button)?.first {
            let location = touch.location(in: button)

            if shapePath.contains(location) == false {
                button.cancelTracking(with: nil)
            }
        }
    }

All of this code belongs into the custom Button class.

Lennart P.
  • 316
  • 1
  • 6
  • 20