Tracking specific regions in UIViews

Audio : Listen to This Blog.

Imagine we need to get the button touch events for the button which has a image set as below. The image area is in the diamond shape (non rectangle).

In normal cases the UIButton events are tracked wherever the user taps inside the button. But what we need is to get the events only when user taps the diamond area.

How we can achieve this? In this article we will find the solution.

We need to create a CGPathRef which contains the required region. A graphics path is a mathematical description of a series of shapes or lines, in our case a shape. In simple terms this is nothing but creating a polygon for the interest area which we want to track inside the UIButton.

Below code explains how to create a CGPathRef/CGMutablePathRef
1. CGMutablePathRef headPath=CGPathCreateMutable();
This creates a mutable graphics path. You are responsible for releasing this object.
2. CGPathMoveToPoint(headPath, NULL, 0, 135); //adding points to head path
Starts a new subpath at a specified location in a mutable graphics path. When you moveToPoint it sets the current point of the path to the specified point.
3. CGPathAddLineToPoint(headPath, NULL, 135, 0);
CGPathAddLineToPoint(headPath, NULL, 270, 135);
CGPathAddLineToPoint(headPath, NULL, 135,270);
CGPathAddLineToPoint appends a line segment to a mutable graphics path.
When you addLineToPoint it draws a straight line from the current point to the specified point.
These three lines is to join the sub paths. Note that the hardcoded values specifies the points which makes the required region.
4. CGPathCloseSubpath(headPath);
CGPathCloseSubpath closes and completes a subpath in a mutable graphics path.
To check the intersection:

if (CGPathContainsPoint(headPath, NULL, location, YES)) {
NSLog(@"inside the interested area…");
} else {
NSLog(@"outside");
}

The api CGPathContainsPoint, checks whether a point is contained in a graphics path.
So the idea behind the intersection calculation is to check if the user tapped location (inside UIButton) is the interested area or not. Its very simple!!
Now how to get the user tapped location?
For this I have sub classed the UIButton and overridden the touch events.
Below is the snippet:
//to check the given touch location is within the valid area
-(BOOL)isValidRegionForPoint:(CGPoint)inPoint;{
BOOL isValid = NO;
CGMutablePathRef headPath=CGPathCreateMutable();

CGPathMoveToPoint(headPath, NULL, 0.0, 120.0); //adding points to head path
CGPathAddLineToPoint(headPath, NULL, 120.0, 0);
CGPathAddLineToPoint(headPath, NULL, 240, 120.0);
CGPathAddLineToPoint(headPath, NULL, 120.0,240);
CGPathCloseSubpath(headPath);
if (CGPathContainsPoint(headPath, NULL, inPoint, YES)) {
// Touched inside myTestRect, do whatever…
isValid = YES;
} else {
}
CFRelease(headPath);
return isValid;
}
Important: Incase the touches happens outside the specific area, we just ignore the touch event by ‘Not calling’ super methods. And hence the action for the button doesn’t trigger.
So its very easy to track the region of interest and fire the events. Go ahead and explore the sample code.
Download from here.
Looking forward your comments. Talk to you soon in next article.
————-

Read Similar Blogs