Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UIImage resizableImageWithCapInsets: not working as expected

I'm writing my first iOS app targeting the iOS 5.0+ platform. I'm using the UIAppearance protocol to customize the applications UI.

I'm trying to change the backgrounds for UIBarButtonItem across the entire application. Due to the fact that my UIBarButtonItem's may change size depending on the text or icon used I'm trying to utilize UIImage resizableImageWithCapInsets: with my background png.

I originally found the code I needed on Ray Wenderlich. Using the same exact code, with an image that's pretty close to the one used in the aforementioned tutorial, I'm getting weird results. Maybe it's just my inexperience with Cocoa Touch.

Here is the code I'm using.

DreamsAppDelegate.m - customizeAppearance:

UIImage *btnBg = [[UIImage imageNamed:@"navBarButton-bg"] 
          resizableImageWithCapInsets:UIEdgeInsetsMake(0, 6, 0, 6)];

[[UIBarButtonItem appearance] setBackgroundImage:btnBg 
                                        forState:UIControlStateNormal 
                                      barMetrics:UIBarMetricsDefault];

Here is the png background image I'm trying to use

png background

And here is the result (in the simulator)

result of trying to use resizableImageWithCapInsets:

like image 413
Brandon Cordell Avatar asked Apr 25 '12 03:04

Brandon Cordell


2 Answers

The section of your image between the left and right, and between the top and bottom, is tiled to fill the space needed by the image. Try UIEdgeInsetsMake(15, 6, 15, 6).

To generalize, if your image has a continuous gradient, the repeated section should only be 1 pixel high. Since your button image is 31 pixels high, the top and bottom (the first and third arguments to UIEdgeInsetsMake) should add to 30. They don't have to be equal; UIEdgeInsetsMake(8, 6, 22, 6) will move the repeated section up, resulting in a paler background.

Also, is the file you've attached the plain or the retina ('@2x') version of the image? The insets have to be within the size of the plain version.

like image 121
Cowirrie Avatar answered Nov 11 '22 15:11

Cowirrie


I have the exact same problem.

Another thing you can do is to set the resizingMode of UIImageResizingModeStretch. It solved my problem.

Hopwever, it's not available in IOS5. So my solution would be to do as everyone else said. Realize that the tileable side should be just one pixel. Most buttons do not change much in the middle anyway.

So, use this code:

-(UIImage *) resizableImageWithCapInsets2: (UIEdgeInsets) inset
    {
        if ([self respondsToSelector:@selector(resizableImageWithCapInsets:resizingMode:)])
        {
            return [self resizableImageWithCapInsets:inset resizingMode:UIImageResizingModeStretch];
        }
        else
        {
            float left = (self.size.width-2)/2;//The middle points rarely vary anyway
            float top = (self.size.height-2)/2;
            return [self stretchableImageWithLeftCapWidth:left topCapHeight:top];
        }
    }
like image 31
Anonymous White Avatar answered Nov 11 '22 16:11

Anonymous White