How to create a capped resizable image prior to iOS5 - ios

Does anyone know how to do this without using [UIImage resizableImageWithCapInsets:]? I'm trying to provide compatibility for users that cannot run iOS5.
UIEdgeInsets imgInsets = UIEdgeInsetsMake(10.f, 5.f, 13.f, 44.f);
UIImage *image = [[UIImage imageNamed:#"fileName"] resizableImageWithCapInsets:imgInsets]; // only available in iOS5+
Please note that I'm not looking to create a 1px stretchable image, I want to tile the area that is defined between the insets when the UIImage is resized. That is, [UIImage stretchableImageWithLeftCapWidth: topCapHeight:] does not do the trick.
Many Thanks!

You can't do this pre iOS 5 in the way you want unfortunately. The only option is [UIImage stretchableImageWithLeftCapWidth: topCapHeight:]. With it you have to specify a single pixel which gets tiled horizontally and vertically. Unfortunately there's no way to do what you want directly with UIImage pre iOS 5.
UPDATED: I've updated this answer because DTs was totally correct.

Related

Xcode image slicing - stretch the outsides of the image but preserve an area in the centre

I want to use image slicing in Xcode to produce a resizable image with a central area that is held static. It seems that this is impossible in Xcode as it only allows for one stretched area and one shrunk area in each direction. Is this correct?
Does anyone know of a nice workaround for this? I need to use the image for a button so I can't do an arrangement of UIImageViews on top of each other unless I pass touches through and that gets a bit messy.
Many thanks.
As stretchableImageWithLeftCapWidth is deprecated with iOS 5.0, You can use resizableImageWithCapInsets. Check Apple Documentation, It states,
You use this method to add cap insets to an image or to change the existing cap insets of an image. In both cases, you get back a new image and the original image remains untouched. For example, you can use this method to create a background image for a button with borders and corners: when the button is resized, the corners of the image remain unchanged, but the borders and center of the image expand to cover the new size.
Another method is also available, resizableImage(withCapInsets:resizingMode:) if you want to set resizingMode
you can do something like,
UIImage *image = [UIImage imageNamed:#"yourImageName"];
UIImage *streachedImage = [image resizableImageWithCapInsets:UIEdgeInsetsMake(5, 5, 5, 5)]; //Edgeinsect that you want
// OR
UIImage *streachedImage2 = [image resizableImageWithCapInsets:UIEdgeInsetsMake(5, 5, 5, 5) resizingMode:UIImageResizingModeStretch];
// OR
UIImage *streachedImage3 = [image resizableImageWithCapInsets:UIEdgeInsetsMake(5, 5, 5, 5) resizingMode:UIImageResizingModeTile];
Check the Documentation for more details.
Update : (According to comment)
You need to just set backgroundImage and image both to your button. You can set image inset also to manage your image's position.

Adding images just for Retina

Is it possible to target users that only have retina displays/have a particular version of iOS? If not, do I need to include non-retina images in my project? I know that for the application icon it needs a non-retina version, but for all of my custom graphics, such as UIBarButton icons, etc. do they all need to have both a retain (test#2x.png) and a regular (test.png) version?
Also, how should I go about scaling? Currently I'm creating say a larger image, like 100x100px and then scaling it down with the following code:
// grab the original image
UIImage *originalImage = [UIImage imageNamed:#"test.png"];
// scaling set to 2.0 makes the image 1/2 the size.
UIImage *scaledImage =
[UIImage imageWithCGImage:[originalImage CGImage]
scale:(originalImage.scale * 2.0)
orientation:(originalImage.imageOrientation)];
Does this maintain a higher resolution than if I re-sized it to 50x50 pixels in photoshop and then added the file into my project as is?
You cannot specify users device.
You'd better add two versions for all images into your app.
Because you could not know whether the device is retina or not.

resizableImage for UIImageView

I am working for IOS 5.0 as minTarget
I have a UIImageView to which i want to assign a resizable image, so that image don't get stretch from corners.
i have tried setting content mode of UIImageView to UIViewContentModeScaleToFill. But the image appears as tiled.
here's the code
UIImage *bgImage = [[UIImage imageNamed:#"ImgViewBg"] resizableImageWithCapInsets:UIEdgeInsetsMake(2, 2, 2, 2)];
imgView.contentMode = UIViewContentModeScaleToFill;
imgView.image = bgImage;
I am looking for the same effect as we have with 9patch images in android
here's the image i am trying on
I just gave an another look at the documentation of resizeableImageWithCapInsets. It says it tiles the the area which is not under cap. I think that what causing the tiled pattern. Is there any workaround to this so that i can have 9Patch style image??
EDIT
According to Apple Docs
upto IOS 5.0 following works for my req.
[[UIImage imageNamed:#"textViewBg"] stretchableImageWithLeftCapWidth:6 topCapHeight:6];
(as mentioned by Dipen Panchasara)
IOS6.0 and later following works for my req.
- (UIImage *)resizableImageWithCapInsets:(UIEdgeInsets)capInsets resizingMode:(UIImageResizingMode)resizingMode
IOS 5.0 and later (which i required)
- (UIImage *)resizableImageWithCapInsets:(UIEdgeInsets)capInsets
above function does not work in my case, as it tiles the image not under cap.
so for IOS 5.0 to IOS 6.0 i was not able to find anything which solves my requirement.
For now i moving to use Dipen Panchasara solution, i hope it stays stable
// Use following code to make stretchableBackground
UIImage *bgImage = [[UIImage imageNamed:#"ImgViewBg"] stretchableImageWithLeftCapWidth:13 topCapHeight:13];
[imgView setImage:bgImage];
ScaleToFill will stretch the image to fill the entire image view. If you don't want to stretch the image and maintain it's aspect ratio, use UIViewContentModeScaleAspectFit OR UIViewContentModeScaleAspectFill.
You can find more information about these constants here.

UIImage strechable image to generate message bubble-like result

I'm trying to implement an strechable image that resembles a dialog bubble however I'm not getting it right,
with the following code:
UIImage *ballon = [[UIImage imageNamed:#"strech.png"] resizableImageWithCapInsets:UIEdgeInsetsMake(12, 11, 12, 9)];
I'm getting the following result:
this is my original leftBubble.png
What could I possibly be doing wrong?
You shouldn't have gradient on the entire image. That's where the lines are coming from. The center of you image (the part that gets stretched, needs to be a solid color since it's getting repeated, not only horizontally, but vertically as well.
If you were only stretching the image horizontally, your image miay have worked just fine.
Try this image I made for you, and use some different capInsets:
UIImage *ballon = [[UIImage imageNamed:#"strech.png"]resizableImageWithCapInsets:UIEdgeInsetsMake(12, 20, 22, 12)];
Notice all of my styling happens on the edge of the bubble, and the center is solid.
EDIT:
Here's a smaller version of the image. I made the larger one so you could see what I was doing.
I can't comment on jhilgert00's answer, but I'd like to add something: -[UIImage resizableImageWithCapInsets:] tiles the inner pixels, rather than stretching, which is why the gradient doesn't work, as jhilgert00 said.
If you're working with iOS 6.0 or higher, you can use -[UIImage resizableImageWithCapInsets:capInsets resizingMode:UIImageResizingModeStretch]
From http://developer.apple.com/library/ios/#documentation/uikit/reference/UIImage_Class/Reference/Reference.html
-(UIImage *)resizableImageWithCapInsets:(UIEdgeInsets)capInsets
[The] pixel area not covered by the cap in each direction is tiled,
left-to-right and top-to-bottom, to resize the image.
and
-(UIImage *)resizableImageWithCapInsets:(UIEdgeInsets)capInsets resizingMode:(UIImageResizingMode)resizingMode
You should only call this method in place of its counterpart if you specifically want your image to be resized with the UIImageResizingModeStretch resizing mode.

How to do [UIImage resizableImageWithCapInsets:] prior to iOS5?

The following code tiles the image area within the specified insets:
UIEdgeInsets imgInsets = UIEdgeInsetsMake(10.f, 5.f, 13.f, 44.f);
UIImage *image = [[UIImage imageNamed:#"fileName"] resizableImageWithCapInsets:imgInsets];
However this is only available in iOS5. How can I achieve the same result for before-iOS5 compatibility?
[UIImage stretchableImageWithLeftCapWidth: topCapHeight:] is not appropriate as far as I understand, because it assumes that the tile-able area is 1px wide. In other words it doesn't tile, it streches. Therefore it doesn't work with patterns, only with single-color images. This is demonstrated in the screenshot below.
Then there is [UIColor colorWithPatternImage:], but this assumes that the entire image needs to be tiled, it doesn't allow for insets that must remain capped.
Any help appreciated, thanks.
.
I've been looking for a solution to this too. At this point I think I'll use respondsToSelector:#selector(resizableImageWithCapInsets:) on the original UIImage to see if the method is available. If not, then use stretchable image.
I'm still looking for a better solution, and if one comes up, I'll update the answer.

Resources