9
UIImage *aImage = [[UIImage imageNamed:@"Gray_Button.png"] stretchableImageWithLeftCapWidth:25 topCapHeight:0];

Trying to make a "glass pill button".

What does "stretch" do if the image is bigger... and the button I'm trying to use it on... is smaller?

Does the image 'stretch' and 'shrink'?

The reason I ask... is because all my images end up look like a "D" shape.

The left side is squared-off... and the right side is rounded.

What would a D-shape tell you that I'm doing wrong? Too much.. or too little... "leftCap setting"? Too large an image?

Susanna
  • 771
  • 3
  • 10
  • 17

2 Answers2

54

A stretchable image is divided into 9 parts, if both leftCapWidth and topCapHeight are nonzero.

     leftCapWidth
      <----->
      +--------------+ ^
      |     | |      | |
      |  A  | |  B   | | topCapHeight
      |-----+·+------| v
      |-----+·+------|
      |  C  | |  D   |
      |     | |      |
      +--------------+

The central parts are always 1 px in size, and this is the part that is stretched, for example:

     leftCapWidth (constant!)
      <----->
      +------------------+ ^
      |     |     |      | |
      |  A  |     |  B   | | topCapHeight (constant!)
    v |-----+ - - +------| v
    | |     .     .      |
    | |     .     .      |
    ^ |-----+ - - +------|
      |  C  |     |  D   |
      |     |     |      |
      +------------------+
            >-----<
        stretched region

To create a "glass pill button", you should fill the rounded border into the regions A, B, C and D above, and supply the radius of that pill into both the leftCapWidth and topCapHeight.


Also, a stretchable image is not shrinkable. If you try to use stretchable images bigger than the buttons (or whatever else) you want to apply it to, they may be rendered incorrectly (especially on older iOSes).

manicaesar
  • 5,024
  • 3
  • 26
  • 29
kennytm
  • 510,854
  • 105
  • 1,084
  • 1,005
  • So a value of 0 would mean "don't stretch anything" or "stretch evenly across the entire image"? I can't see anything that would cause a "D-shaped" problem. I guess the first thing I should do is make sure EVERY image smaller than EVERY button. (If not... then what happens? The image is just used "as-is" sized? And what becomes of the cap-value stretches that won't happen?) – Susanna Jun 14 '10 at 16:01
  • @Roberta: 0 means "stretch evenly across the entire image". If the image is smaller than the corners will overlap with each other. – kennytm Jun 14 '10 at 16:06
  • 1
    The illustration is really helpful. – nonamelive Sep 20 '11 at 05:09
  • 1
    "Also, a stretchable image is not shrinkable" - that was my problem - I have to big png backgrounds and were trying to apply them to buttons with smaller frames. Thanks, +1! – manicaesar Jul 17 '12 at 14:01
  • resizableImageWithCapInsets works fine on downscaling, but available only in iOS 5.0+ – Pavel Alexeev Sep 13 '12 at 08:59
3

stretchableImageWithLeftCapWidth does not behave as you would expect. I suggest using UIView's contentStretch property instead to save yourself some frustration.

FYI, the way stretchableImage behaves is:

  • if you shrink the image, it just clips the top and left parts of the image rather than stretching anything.
  • if you expand the image, it will expand only the column of pixels just beneath the top cap and the row of pixels just right of the left cap. This works for very simple graphics but will look awkward for any graphics that have effects like shading or gloss.

contentStretch, on the other hand, behaves just as you would expect. The graphic basically gets split into 9 parts that expand AND CONTRACT the way Kenny explained.

Also, don't forget that anytime you stretch a view, its contentMode should be set to UIViewContentModeScaleToFill.

Micah Hainline
  • 14,367
  • 9
  • 52
  • 85
Rolf Hendriks
  • 271
  • 3
  • 3
  • This is not true. As @KennyTM explained, they do not CONTRACT that way: the caps are not respected if the image needs to be downscaled. – Dan Rosenstark Feb 12 '11 at 01:22