Is there a nine-patch loader for iPhone?
Asked Answered
I

4

27

Android has a nice way of defining stretchable images called a nine-patch. See these docs for a description of the concept. The idea is to surround a png image with a 1-pixel border where you can define the stretchable areas and the padding dimensions of the image. This is absolutely brilliant and I'd like to use the idea in my iPhone app. Before writing my own nine-patch to UIImage loader I thought I'd see if one already exists. Google doesn't return any results so I don't have much hope, but it doesn't hurt to ask, right? :-)

EDIT: Folks, I appreciate the answers but I know about stretchableImageWithLeftCapWidth.... I'm looking for code that takes a path @"foo.9.png" and returns a stretchable UIImage. This code will undoubtedly use stretchableImageWithLeftCapWidth... internally. I'm sure I could write the code myself using that method. But I'm asking if somebody else has already done it.

Ibsen answered 16/7, 2009 at 0:25 Comment(2)
Good idea. Do it and post the source!Mcvay
I have reported a feature request on this at bugreport.apple.com please do the same. The more people that report the same bug/feature request the more likely that Apple devote their time. Trust me it works.Choli
I
25

I received an e-mail from Tortuga22 software who informed me that they have created such a library and released it under the Apache license:

Announcement: http://blog.tortuga22.com/2010/05/31/announcing-tortuga-22-ninepatch/

Source code: http://github.com/tortuga22/Tortuga22-NinePatch

Example usage:

// loads-and-caches ninepatch and rendered image of requested size
UIImage buttonImg = [TUNinePatchCache imageOfSize:buttonSize 
                                forNinePatchNamed:@"buttonNormalBackground"];
[self.buttonNeedingBackground setImage:buttonImg
                       forControlState:UIControlStateNormal];
Ibsen answered 2/6, 2010 at 16:46 Comment(4)
as far as I understand Tortuga’s comments on the drawbacks, this library only supports a stripped down version of ninepatches. ninepatches with non-contigeous areas (such as speech bubbles with dynamically aligned [e. g. centered] arrows) are not supported.Schreibe
It also seems to me that this library only supports "source" versions of NinePatch (the one with 1 transparent pixel around the image).Redress
Hai gray i also used Tortuga22-NinePath,it works in simulator,but i install in device it shows error "Undefined symbols for architecture armv7s:"_OBJC_CLASS_$_TUNinePatch", referenced from:".is any way NinePatch image run in device?Superego
@Superego did you add TUNinePatch sources into compile sources section in xcode ?Racer
A
4

Also look at UIView's contentStretch property. It is more robust and well-behaved than stretchableImageWithLeftCapWidth. Basically, it works by just defining the stretchable rectangle within your image and automatically creating a scaled nine-patch. This internal rectangle can be anything - it doesn't even have to be in the center of the image. Plus unlike stretchableImage this method will properly shrink graphics and behave as expected for graphics with lighting or gloss. I can't think of any real-world application where you would want more than this.

Ant answered 13/8, 2010 at 15:53 Comment(2)
i always wondered how it'd be possible to use this implementation to set a background of a button. The Apple's stretchableImageBlablabla just doesn't cut it for more advanced buttons where you want to specify a rectangle to stretch rather than a single pixel in each direction. Any ideas on that?Tuscany
Agreed, but stretchableImage... got even simpler in iOS 5 when the (UIImage *)resizableImageWithCapInsets:(UIEdgeInsets)capInsets was added - this allows the top, bottom, left and right non-stretchable insets to be specified separately.Suanne
G
3

Yes UIImage does support something like it. See

- (UIImage *)stretchableImageWithLeftCapWidth:(NSInteger)leftCapWidth topCapHeight:(NSInteger)topCapHeight and the documentation for leftCapWidth and topCapHeight

basically the image is not stretched in the area leftCapWidth pixels from the left and right edge and topCapHeight pixels from the top and the bottom. When the image is scaled the area inside of these limits is subject to stretching.

Golanka answered 16/7, 2009 at 2:32 Comment(3)
I know about that method, but it has the disadvantage of requiring the cap height/width to be stored separately from the image. What I like about nine-patch is how the image file has all the information necessary to describe its scaling behavior.Ibsen
You don't have to keep the values around. the method returns a new image with those values baked in.Prosthesis
It's not about keeping the values around. It's about having a single file "foo.9.png" that stores both the image and the information for stretching it correctly. With 9-patch files I can replace an image resource in my project and know that it will stretch correctly without changing a line of code. With this method that's not the case -- I have to be sure I've adjusted the cap width/height values in my code.Ibsen
P
1

All UIImage images support this natively. By default the entire images is stretchable, but you can set caps with the leftCapWidth and topCapHeight properties or you can generate one from an existing UIImage with the - (UIImage *)stretchableImageWithLeftCapWidth:(NSInteger)leftCapWidth topCapHeight:(NSInteger)topCapHeight method.

Do note that in apple's implementation, when you set one or both of these values, the stretchable area is forced to be a single pixel high/wide.

Prosthesis answered 23/8, 2009 at 13:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.