By default, the buttons on iOS are rectangular shaped. In most situations in which a developer can be that’s enough and we can do most of the things.
But sometimes, application requirements are such that we need a different approach to resolve that situation. Let’s say you need the area of the button to be a circle or a triangle, the rectangular approach can’t be used here.
Problem
Let’s imagine that we need the UI shown on image. We have 8 buttons where every button is a triangle. Every button is represented by a different color and when someone clicks on a color we will present that color.
With classic UIButton we don’t have a way to do this, buttons will overlap and it will be difficult to do what we want.
Solution
Our approach to resolving this is the UIButton subclass. There is a great method:
– (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
defined on UIView which we will override in our subclass. The basic idea is very simple: we will return button if touch point is inside the area we are interested in, otherwise we will return nil which means that we don’t want to receive the touch event and it will be forwarded further if someone else is interested to receive it.
Note that this method is defined on UIView class which means that we are not limited on UIButton but all UIView subclasses.
Technicalities
Now we know what we want and how to do it. It’s now a question of how exactly we will implement this. The way we will do this is:
- Insert 8 buttons in xib file, one button for each area.
- Insert outlets and create an array of those buttons. We will pass the array to the utility class.
- Create utility class in which we will put methods related to button shapes.
- In the utility class create three arrays of points. The first array will contain the first point of triangle for each button. The second array will contain the second point of triangle for each button, and finally the third array will contain the third point of each triangle.
CGPoint points1[8] = {{0, 0}, {70, 30}, {100, 0}, {70, 70}, {100, 100}, {30, 70}, {0, 100}, {30, 30}}; CGPoint points2[8] = {{70, 30}, {100, 100}, {70, 70}, {0, 100}, {30, 70}, {0, 0}, {30, 30}, {100, 0}}; CGPoint points3[8] = {{0, 100}, {0, 100}, {0, 0}, {0, 0}, {100, 0}, {100, 0}, {100, 100}, {100, 100}};
UIBezierPath *bezierPath = [UIBezierPath bezierPath]; [bezierPath moveToPoint:point1]; [bezierPath addLineToPoint:point2]; [bezierPath addLineToPoint:point3]; [bezierPath closePath];
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event { UIBezierPath *path = [[PNTUtility sharedUtility] bezierPathForButton:self]; if ([path containsPoint:point]) { return self; } else { return nil; } }
You can check the example project on our github repo: https://github.com/Planet1107/CustomShapedButtons/
Conclusion
We mentioned that we are not limited to UIButton nor the triangles. You can create whichever shapes you want. The only thing that needs to be changed are the points that will define your shape. So next time when your designer has a “great idea” that will complicate your life, maybe this will help you. :)
Leave Your Comment