This UI control can be created using the UISegmentedControl Class, available in the UIKit framework. The appearance of this control can be easily customized, yet how to do that is not always apparent to new iOS developers. I was recently asked to create a row of separate buttons that would behave similarly to UISegmentedControl
. That is, only one button could be selected at any given time. The design looked something like this (specifically this one I took from dribbble):
Generally speaking, the appearance of the UISegmentedControl
could be customized by using the following methods that set the background and divider images:
The background image fills the stretchable parts of the control segments and their edges. Therefore, this image should have equal-sized left and right parts used for the left and right edges of the control, respectively. These two parts must be separated by a 1-pixel wide line (2 pixels for retina images). This line is used to fill the control segments by stretching itself horizontally. The divider images are used to fill the space between the control segments. These images are used “as is” without being stretched, and therefore their width defines the space between the control segments. The following diagram shows how these images are used in UISegmentedControl
:
After we know how UISegmentedControl
uses these images to present itself, we can write some code to customize its appearance. In the following example, I have created a subclass of UISegmentedControl
called MySegmentedControl,
which has all the needed code to customize the appearance of our control. By the way, subclassing is not required, and everything that is shown here could be done by sending those same messages (an Apple’s terminology for “method invocation”) to an instance of the UISegmentedControl
class.
First, we need to create all five images: two background images for the selected and normal (unselected) states and three divider images. The three divider images are used for:
Then we need to create a subclass of UISegmentedControl
, by creating a header and an implementation file:
In the implementation file for MySegmentedControl
we will override the designated initializer - (id)initWithItems:(NSArray *)items
and call the appearance methods:
We are not finished just yet – if we embed the code above in a UIViewController
we will see that the text inside the control’s segments is not aligned properly. The following code will produce undesired results:
And the result:
So why is this happening? Well, the answer is hidden in the implementation of UISegmentedControl
. What happens is that UISegmentedControl
center-aligns text inside its segments according to their width, but the segment’s width doesn’t include the divider images. Here’s a diagram to clarify things:
To solve this issue we need to adjust the content position of the first and last segments by 1/2 the width of the divider images, assuming that all divider images have the same width. To do this we need to add two lines of code to MySegmentedControl
:
And with that we reach our final result: