Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
375 views
in Technique[技术] by (71.8m points)

objective c - Using resizableImageWithCapInsets: image for button only works for the state set, other states show a "gap"

When using resizableImageWithCapInsets: to create an image for a UIButton only the normal state (the state set the image with using setBackgroundImage:forState:) works. All other states show a gap instead of the drawn image. UIButton says that if no image is set for a particular state, the normal state image will be used with an overlay for disabled and selected states.

Here is the normal state:

enter image description here

Here is the selected state:

enter image description here

And here is the source image:

enter image description here

It clearly is using the resizable image I provided, but the image is not drawing the resized area. (You can see the left and right edges but the middle area that is to be stretched just isn't drawn).

Interestingly, stretchableImageWithLeftCapWidth:topCapHeight: does work. Now this is a deprecated method in iOS 5, but with the gap being shown in the new API, I may be stuck using it.

I do recognize that I can provide more images for each state but that defeats the purpose I'm trying to achieve of reducing memory footprint plus adds extra dependency on my graphics designer which I'd like to avoid.

// This is the gist of the code being used
UIImage* image = [UIImage imageNamed:@"button.png"];
UIEdgeInsets insets = UIEdgeInsetsMake(image.size.height/2, image.size.width/2, image.size.height/2, image.size.width/2);
image = [image resizableImageWithCapInsets:insets];
[self.button setBackgroundImage:image forState:UIControlStateNormal];
// Even doing the following results in the same behaviour
[self.button setBackgroundImage:image forState:UIControlStateSelected];
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You aren't creating your insets properly for the image capping. I've reproduced your issue and corrected it by using the correct insets.

With your current code, you are creating caps of half of the image height and width - this leaves you with a "stretchable" area of 0x0 pixels - so you get nothing in the middle.

Why this isn't showing up as wrong in the normal state of the button I'm not sure - perhaps there is some optimisation built in to UIButton to fix things or auto-strectch if you don't supply a stretchable image, and this is not applied to the other states.

The caps are supposed to define the area of the image that must not be stretched. In the case of your button.png image, this is 6 pixels on the left and right sides, and 16 pixels in from the top and bottom. This isn't quite standard, you should tell your graphics designer that (at least for left-right which is the most common stretching) you should only have a 1px area in the centre, however this does not affect the outcome. If you do have a 1px stretchable area then you can standardise your code by deriving the caps from the image size as you have tried to do in your question (each cap is then (image.size.height - 1) / 2 for top/bottom, same but with width for left/right).

To get the correct images on your button, use the following code for creating the stretchable image:

UIEdgeInsets insets = UIEdgeInsetsMake(16, 6, 16, 6);
image = [image resizableImageWithCapInsets:insets];

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...