iOS Programming Recipe 2: Skinning UIButton

Before You Begin

This recipe uses resizable graphics that were generated using Opacity which was the topic of another of our posts, Developer Tools – Opacity. If you are following along you can download both the 1x and 2x graphics here.

Skinning UIButton

I have seen many different approaches to creating custom looking UIButtons

  • UIButton subclass implementing drawRect
  • Drawing the background images once, then caching and reusing
  • creating images asset for each button size

While each of these methods may technically work, the best method is to use resizable image assets. Using resizable assets will allow you to take full advantage of UIKit and the performance enhancements it has to offer.

iDevices these days come in many shapes an sizes, retina and non-retina screens, ect, so it is important that you create assets at different resolutions so your application looks great on all of them!

Step 1: Setup a UIButton

  • Create a new Xcode project using the single view application template for iOS or use an existing application if you have one.
  • Open ViewController.xib and drag two UIButton’s from the object pane into your view, your view should look like the one below

ViewController_image

  • In Interface Builder, open the Attributes Inspector Option+CMD+4, then select the second button, change the Type property to Custom as shown below

IB_Type_Property_Custom

  • If you’re using Auto Layout, you may need to add a constraint between your button so they don’t overlap during run-time on different size devices, select both buttons, then hit the middle button Add Constraint located in the lower right corner of IB. Select Vertical Spacing
  • Create an outlet for the second button in ViewController.h
@interface ViewController : UIViewController

@property (strong, nonatomic) IBOutlet UIButton *styledButton;

@end
  • Back in ViewController.xib, link the IBOutlet in Interface Builder by ctl+dragging from “File’s Owner” to the second button, when the HUD shows up select “styledButton” or your property name if different.
  • Build and Run to ensure everything ok

Step 2: Styling the Button

  • Add the resizable image assets to your project.
  • The 1x image “image.png” has a size of 33 x 44, so this image asset will look good on any button of height 44 (the default UIButton height) independent of it’s width (because it will be resizable!).
  • Add the following code to viewDidLoad in ViewController.m
#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.

//create the image
UIImage *resizableButtonImage = [UIImage imageNamed:@"image"];

//create the edge insets, which define how the image should be streched
UIEdgeInsets insets = UIEdgeInsetsMake(0.0f, 16.0f, 0.0f, 16.0f);

//make the image resizable
resizableButtonImage = [resizableButtonImage resizableImageWithCapInsets:insets];

//set the image on the button
[self.styledButton setBackgroundImage:resizableButtonImage forState:UIControlStateNormal];
}

- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}

@end
Code Explaination
  1. First creates a UIImage from one of the images we added to the project. Just by specifying it by name image instead of image.png or image@2x.png UIKit is smart enough to use the 1x resolution image on a non-retina device and the 2x version on a retina device. The important thing here is to follow the convesion of the name followed by @2x for the high resolution version.
  2. Next we create the UIEdgeInsets which set how the image should be resized. In this case we do not want to resize in the vertical direction so the top and bottom edge are set to 0.0f. What we want is to resize one vertical row of pixels in the very center (if more than one pixel is choosen to resize, Core Graphics will tile the section which is a little bit less efficient, so choose only one pixel if possible). Since the image is 33 pixels in width, so 16.0f on the left and 16.0f on the right leave one pixel in the center for streching.
  3. We then make the image resizable by calling resizableImageWithCapInsets: and setting our insets.
  4. Finally, we set the resizable image to the backgroundImage property of our button, in this case I just set it for the normal button state, but if you wanted a different image for when the button is selected you could set that as well.
  5. Build and Run, your customized button should now look… well custom!

Finished_Custom_UIButton

That’s It!

Hope this is helpful! Until next time good luck with all your UIButton customizing!

Comments

  1. Thank you Mike. This was very helpful to me. One thing … how do I add code to handle a selected state of the button using images that resize?

    THanks !

  2. I did it like this and it worked. For anyone who wants to use an image for the highlighted state as well. Otherwise the default is the ‘reverse on highlight’ typical ios look.

        //create the image
        UIImage *resizableButtonImage = [UIImage imageNamed:@"btn-text"];
        UIImage *resizableButtonImageOn = [UIImage imageNamed:@"btn-text-on"];
       
        //create the edge insets, which define how the image should be streched
        UIEdgeInsets insets = UIEdgeInsetsMake(23.0f, 26.0f, 23.0f, 26.0f);
       
        //make the image resizable
        resizableButtonImage = [resizableButtonImage resizableImageWithCapInsets:insets];
        resizableButtonImageOn = [resizableButtonImageOn resizableImageWithCapInsets:insets];
       
        //set the image on the button
        [self.styledButton setBackgroundImage:resizableButtonImage forState:UIControlStateNormal];
        [self.styledButton setBackgroundImage:resizableButtonImageOn forState:UIControlStateHighlighted];

Speak Your Mind

*

css.php
Privacy Policy