Define custom touch area in custom UIControl object

ios, uicontrol

Solution

You can override UIView's `pointInside:withEvent:` to reject unwanted touches.

Here's a method that checks if the touch occurred in a ring around the center of the view:

- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
{
    UITouch *touch = [[event touchesForView:self] anyObject];
    if (touch == nil)
        return NO;

    CGPoint touchPoint = [touch locationInView:self];
    CGRect bounds = self.bounds;

    CGPoint center = { CGRectGetMidX(bounds), CGRectGetMidY(bounds) };
    CGVector delta = { touchPoint.x - center.x, touchPoint.y - center.y };
    CGFloat squareDistance = delta.dx * delta.dx + delta.dy * delta.dy;

    CGFloat outerRadius = bounds.size.width * 0.5;

    if (squareDistance > outerRadius * outerRadius)
        return NO;

    CGFloat innerRadius = outerRadius * 0.5;

    if (squareDistance < innerRadius * innerRadius)
        return NO;

    return YES;
}

To detect other hits on more complex shapes you can use a `CGPath` to describe the shape and test using `CGPathContainsPoint`. Another way is to use an image of the control and test the pixel's alpha value.

All that depends on how you build your control.

Problem

I am creating a custom UIControl object as detailed here. It is all working well except for the touch area. I want to find a way to limit the touch area to only part of the control, in the example above I want it to be restricted to the black circumference only rather than the whole control area. Any idea? Cheers

Original source