Aug 22, 2013

Custom iOS Components: Scaling Background Images

Overview

When developing custom components like buttons or tabs, there's often a need to have those components in variety of sizes for different views/purposes.

For example, one view might have two tabs and another one might have three tabs. Even though basic tab background is the same, it will often have borders or shadows at the sides which can't be stretched. That's why many developers come up with most common solutions:

a) Saving the same background in all required sizes
b) Saving background picture by parts (top/bottom/middle or left/right/middle) with further combining

Apple has actually very elegant single line solution for this problem. Let's say we are developing custom alert view and our background looks like this :


Red lines mark the area which can't be stretched due to color variations and rounded corners (40 pixels at the top and 25 pixels at left, right and bottom), but everything else inside is basically single solid color which can be resized as wanted.

Basically you just need to "tell" iOS which parts of picture should not be stretched. Let's assume image name is "alert_bg.png".

For iOS 5 and up the following method does the trick:

AlertBg = [[UIImage imageNamed@"alert_bg.png"resizableImageWithCapInsets:UIEdgeInsetsMake(40.025.025.025.0)];


For earlier iOS versions you should use slightly different version:

AlertBg = [[UIImage imageNamed@"alert_bg.png"stretchableImageWithLeftCapWidth25 topCapHeight40];



And combined universal solution:


if ([AlertBg respondsToSelector:@selector(resizableImageWithCapInsets:)])
    AlertBg = [[UIImage imageNamed@"alert_bg.png"resizableImageWithCapInsets:UIEdgeInsetsMake(40.025.025.025.0)];
else
    AlertBg = [[UIImage imageNamed@"alert_bg.png"stretchableImageWithLeftCapWidth25 topCapHeight40];

Summary

This approach is also great for saving space - you can store minimal size backgrounds for buttons, tabs, etc with further image expansion.