Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iOS Stretchable image on UIButton showing wonky corners

Tags:

ios

iphone

OK folks,

I've searched all over and cannot seem to find a solution to my issue.

I am trying to use a sizeable image for a button background to get a custom look for a UIButton and to reduce the overall size of the app and because it seems like the right thing to do.

However, when I try to set the image on the button the button gets all weird looking and the corners do not match the standard corner radius of a regular UIButton.

I have tried creating several different sizes of images but nothing I do seems to work.

I know the caps are supposed to be even and I have that plus the 1 pixel middle to stretch.

My UIButton is 44 high. If I create an image that is 44 pixels high and 21 pixels wide and has the same rounded corner radius as the default button (it likes an aspirin caplet) and set my background image like this:

UIImage *btnImage = [UIImage imageNamed:@"buttontest1.png"];
UIImage *newImg = [btnImage stretchableImageWithLeftCapWidth:10 topCapHeight:0];

the corners just don't match and look weirdly widely stretched AND the button grows in height!

I know the stretchableImagewithLeftCapWidth is deprecated but the usage of resizableCapWithInsets makes even less sense to me and when I try to do that the button image just seems to repeat over and over.

Can anyone figure out what I'm doing wrong? Is there anyplace that explains this crap simply? I just cannot seem to get it.

Thanks! -TJ

EDIT - adding images after using the resizableImageCapWithInserts to show results. They can't be typical as I see examples all over that supposedly work but the examples never work for me. I just figured out how to add images here so maybe this helps some.

My PNG file 21pxels wide by 29 pixels tall Here is the PNG file 21px wide by 39px tall

Results of my code This is the result of using the following code to set the background image:

[self.button1 setBackgroundImage:[[UIImage imageNamed:@"buttontest4.png"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 10, 0, 10)] forState:UIControlStateNormal];

As I understand it this should copy the left 10 pixels and right 10 pixels of my 21 pixel wide image as is and stretch the middle 1 pixel across, which it appears to do but it is also making my button get larger vertically and I'm getting this weird repeat. It should be the same size as the BTN next to it.

Here is my Xcode layout: Xcode layout

No matter what image I use I see similar results.

I'm obviously not groking something here.

I appreciate the answers so far. It's becoming slightly less foggy.

TJ

EDIT2: showing samples using the cap insets method with image 21px by 44px.

All 4 buttons are 44px high when designed in storyboard.

both buttons 44px high As you can see the orange buttons are both larger than the white buttons for scale comparison.

The top button is button1, bottom is button2.

I found a way to get it closer by using the optional resizingMode parameter of UIImageResizingModeStretch.

However, notice the buttons are larger than what they should be.

Here is the code for setting the button images.

- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.

[self.button1 setBackgroundImage:[[UIImage imageNamed:@"buttontest1a.png"] resizableImageWithCapInsets:UIEdgeInsetsMake(10, 10, 10, 10)] forState:UIControlStateNormal];

[self.button2 setBackgroundImage:[[UIImage imageNamed:@"buttontest1a.png"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 10, 0, 10) resizingMode:UIImageResizingModeStretch]  forState:UIControlStateNormal];
}

Doing the top image with (10,10,10,10) gets me an image that does not repeat the top part of the image like previously. I know the top image is not using the optional resize parameter as this is a test to see what each gets me.

Now, to complicate things even more. If I set my top button size to 43, that is one pixel smaller than my image and make a call with the optional resize parameter I get nearly perfect results except my button is not the right size.

What the heck is going on here?

I appreciate everyone who is trying to pound some knowledge through my thick skull. TJ

buttons 43 and 44

like image 577
TJ Asher Avatar asked Dec 12 '22 22:12

TJ Asher


2 Answers

UIEdgeInsets is a little difficult to wrap your head around, but it is the more modern usage. I will explain the way it works. Basically, using four offsets, you are dividing your image into 9 slices. If you want to see an image of what this potentially looks like, have a look at the "Scaleable area" section of this page (Note, it is for Android, but the concept is the same. Android was just doing it first). You will notice four lines going through the image. These will correspond to your four insets. So your nine sections, from left-to-right and top-to-bottom will be:

  1. X: 0 -> Left Inset, Y: 0 -> Top Inset
  2. X: Left Inset -> (Width - Right Inset), Y: 0 -> Top Inset
  3. X: (Width - Right Inset) -> Width, Y: 0 -> Top Inset
  4. X: 0 -> Left Inset, Y: Top Inset -> (Height - Bottom Inset)
  5. X: Left Inset -> (Width - Right Inset), Y: Top Inset -> (Height - Bottom Inset)
  6. X: (Width - Right Inset) -> Width, Y: Top Inset -> (Height - Bottom Inset)
  7. X: 0 -> Left Inset, Y: (Height - Bottom Inset) -> Height
  8. Left Inset -> (Width - Right Inset), Y: (Height - Bottom Inset) -> Height
  9. X: (Width - Right Inset) -> Width, Y: (Height - Bottom Inset) -> Height

Sections 1, 3, 7, and 9 are set and will not stretch.
Sections 2 and 8 will stretch horizontally only
Sections 4 and 6 will stretch vertically only
Section 5 will stretch in both directions.

New in iOS 6, you can select a mode. You can either stretch the stretchable tiles, or repeat them to get the effect that you want (colors, etc should stretch while textures should repeat).

like image 84
borrrden Avatar answered Jan 07 '23 19:01

borrrden


Try UIEdgeInsets

[button setBackgroundImage:[[UIImage imageNamed:@"buttontest1.png"] resizableImageWithCapInsets:UIEdgeInsetsMake(10, 10, 10, 10)] forState:UIControlStateNormal];
like image 41
endy Avatar answered Jan 07 '23 21:01

endy