This post describes how to create rounded rect buttons with variable length using a rectangular background graphic as a basis. This method requires iOS SDK 3.0 or higher. The information presented is not new, but I had to dig somewhat into Stackoverflow to find all the bits, so I thought a summary might be in order. This post is my idevblogaday contribution.
Background
Recently I wanted to create some decent looking buttons for a small app I wanted to release without spending money for graphic assets other than the Icon. So I spent a joyful morning in Acorn to create a brushed metal background (which was easy) and custom brushed metal buttons on top (which was a nightmare, but not because of Acorn).
When you do your own rounded corners (which Acorn supports nicely), you got to adjust the corner angle differently for your retina buttons. And when you have buttons with different lengths, I found pretty much every resizing method created artifacts that made the button look dirty.
I got somewhat industrious with cutting and pasting and stretching only the middle segment, ending with a heap of button graphics, four for each length (Default, Highlighted x 2 for retina), and ultimately I wondered if there isn’t a simpler way to do it with Interface Builder.
Well. There is not. You either select the “Round Rect” type, which will not have rounded corners anymore when choosing a rectangular background graphic or you use the “Custom” type which makes the button form rectangular right away.
So I wondered if there is a programmatic way to do it and there is, like here. But it feels like implementing a ton of code for a small cosmetic thing. Looking closer, I found that pretty much all examples I found were based in the pre 3.0 SDK age. Now, I’m using 4.3 for all newer apps and I certainly don’t target anything below 3.0 anymore. If you are in the same boat, making custom rounded rect buttons is really simple.
Import
With iOS 3.0 and higher you can use UIButtons CALayer to dynamically change its style. Make sure you import
#import <QuartzCore/QuartzCore.h>
Create
In Interface Builder, select the UIButton you want to change. Choose “Custom” type and select your background graphic. For my example below, this is a simple rectangular png with a gradient metal effect.
When creating such a base graphic, I typically choose 200×74 as size for the retina version. For shorter buttons, it will be compressed horizontally which is not visible afaic.
Code
A typical approach to access a button created in Interface Builder is to connect it via IBOutlet. The code for re-shaping that rectangular custom button looks like this and can be placed in viewDidLoad
_myButton.layer.cornerRadius = 8;
_myButton.layer.borderWidth = 1;
_myButton.layer.borderColor = [UIColor grayColor].CGColor;
_myButton.clipsToBounds = YES;
And that’s all it takes.
Tags
When I have a bunch of buttons in a view that should receive that treatment, I started to arrange them in a certain tag range, like 30+. So button 1 gets tag 30, button 2 gets tag 31, and so on. Which allows a simple loop like
for (int i=30; i<_lastCustomButtonTag; i++) {
UIButton* button = (UIButton*) [self viewWithTag:i];
button.layer.cornerRadius = 8;
button.layer.borderWidth = 1;
button.layer.borderColor = [UIColor grayColor].CGColor;
button.clipsToBounds = YES;
}
And here is the main screen of my current project which I will release this week, an app where I test a bunch of AVFoundation functionality I’ve been looking into, showing pictures of cute kittens and dogs while secretly recording the viewer with the front-facing camera. Note I also created my own UISegmentedControl out of buttons just to match the style, although you cansee the highlighting is not exact, a UISegmentedControl would not show the blue bottom border line for the highlighted segment.
I hope people find this simple approach useful.



[...] A simple way to create custom Rounded Rect Buttons [...]
This is a great tip Markus – thank you!
I also wanted to suggest another alternative to the tagging for doing the different setups on your buttons.
You could alternatively create several OutletCollection’s of your UIButtons. One collection for each of the types of treatment you want to apply. In interface builder you’d then just connect the buttons to the appropriate collection and run a for loop over the collection:
for( UIButton *aButton in self.buttonTreatment1Collection )
{
// aButton tweaking code here
}
Just a thought – the tagging also of course works just fine.
Cheers
great idea! afaik, OutletCollections require 4.0 and higher but that’s pretty much the only caveat. Thanks for sharing!