I am creating this structured through masks:
Each hexagon should be clickable. This is the code I used:
// To create one masked hexagun
let hex = UIImage(named: "hexum")
let mask = CALayer()
mask.contents = hexum!.CGImage
mask.frame = CGRectMake(0, 0, hex!.size.width, hex!.size.height)
let img = UIImageView(image: UIImage(named: "img"))
img.layer.mask = mask
img.layer.masksToBounds = true
// Gesture Recognizer
let singleTap = UITapGestureRecognizer(target: self, action: "tapDetected")
singleTap.numberOfTapsRequired = 1
img.addGestureRecognizer(singleTap)
img.userInteractionEnabled = true
func tapDetected() {
print("Clicked!")
}
The problem is that the click region is larger than the mask, which will cause the inconvenience of a region overlapping each other. Something like this:
The yellow border shows the clickable region (not actually visible)
I am a beginner, it may be a trivial problem, but can you help me solve? Thank you.
If you want to do this perfectly, use the UIGestureRecognizerDelegate
method gestureRecognizer(gesture, shouldReceiveTouch: touch) -> Bool
. You will need to map the given gesture recogniser to a particular hexagon and then do pixel precise hit-testing on the image for that hexagon. This latter part is achieved by rendering the mask image to a graphics context and finding the pixel at the point corresponding to the touch location.
However, this is likely overkill. You can simplify the problem by hit-testing each shape as a circle, not a hexagon. The circle shape roughly approximates the hexagon so it will work almost the same for a user and avoids messy pixel-level alpha equality. The inaccuracy of touch input will cover up the inaccurate regions.
Another option is to rework your views to be based on CAShapeLayer
masks. CAShapeLayer
includes a path
property. Bezier paths in UIKit include their own rolled versions of path-contains-point methods so you can just use that for this purpose.