Using stretchable images in iOS

Stretchable images are used quite often for different customization scenarios. First of all it’s a future-proof solution that will not require replacing assets each time you resize elements in your views. Secondly it’s an application’s size optimization, because you can avoid duplicates for elements with different sizes.

Stretchable images can be used to customize many controls: UIButton, UITextView, UITextField, and so on.

Let’s look into example where stretchable images could be useful:

Non-stretchable image to customize UIButton control

As you can see, “Big Button” stretches background image in a wrong way. To fix this we need to convert our image into stretchable image. To do that you need to select your image in .xcassets folder in Xcode and check Editor->Show Slicing in top menu. (You can change it back to Editor -> Show Overview anytime):

Changing image preview mode in Xcode

Now, the only thing we need is to set “stretchable” and “non-stretchable” areas of our image. Images can be stretched in three ways: Only horizontally stretchable image, Only vertically stretchable image and Both horizontally and vertically stretchable image.

Such image has 9 regions:

  • Top-Left corner: Immutable part, will be placed to top-left corner of result area.
  • Top border: Horizontally stretchable part, will be stretched between Top corners.
  • Top-Right corner: Immutable part, will be placed to top-right corner of result area.
  • Left border: Vertically stretchable part, will be stretched between Left corners.
  • Center area: Both directions stretchable part, will fill all the area inside.
  • Right border: Vertically stretchable part, will be stretched between Right corners.
  • Bottom-Left corner: Immutable part, will be placed to bottom-left corner of result area.
  • Bottom border: Horizontally stretchable part, will be stretched between Bottom corners.

To better understand what means stretchable and non-stretchable regions, I will provide an example image:

Stretchable and non-stretchable regions of image

All other area (disabled-like white out area) will be ignored. There is a nice place for optimization, but we’ll talk about it little later in this article.

Because in our example we have an image that should be stretched in both directions - we use vertical and horizontal slicing:

Define stretchable image regions using Xcode assets editor

You can also make image stretchable in code:

UIImage(named: "FancyButton")?
    .resizableImageWithCapInsets(
        UIEdgeInsetsMake(4, 4, 4, 4),
        resizingMode: UIImageResizingMode.Stretch
    )

or

UIImage(named: "FancyButton")?
    .stretchableImageWithLeftCapWidth(
        4,
        topCapHeight: 4
    )

Now we have nicely stretchable image and can define any button size:

Stretchable image in action

Now when our image is stretchable we need to think about optimization. Because we do not use most parts of our image, we can simply cut them out:

Optimized image

It will save us some amount of application size:

  • x1: original image 431 bytes -> optimized image 164 bytes
  • x2: original image 1 kb -> optimized image 214 bytes
  • x3: original image 2 kb -> optimized image 258 bytes

In total we save ~3 kb for one single image. It could be quite small comparing to our total application size but with more images - size can increase dramatically and even affect application’s loading time.

Updated:

Leave a Comment