UIImage how to resize bubble image with capInsets?

2019-08-04 16:19发布

问题:

I have bubble like image, that I need to resize dynamically. Example attached. I will have dynamic text and I need to resize only straight parts of bubble. Leave down arrow on the middle How can I do this? Thanks

回答1:

You can use method:

- (UIImage *)stretchableImageWithLeftCapWidth:(NSInteger)leftCapWidth topCapHeight:(NSInteger)topCapHeight;

call like this:

UIImage* image = [[UIImage imageNamed:@"bubbleImageName.png"]
                       stretchableImageWithLeftCapWidth:15 topCapHeight:13];

Change capWidth and capHeight values



回答2:

I think that resizableImageWithCapInsets: will be pretty useful for you

Example:

UIImage *image = [[UIImage imageNamed:@"buttonImage"] resizableImageWithCapInsets:UIEdgeInsetsMake(5.0,10.0,5.0,10.0)];
[self.yourButton setBackgroundImage:image forState:UIControlStateNormal];

I wrote example with button because it's a common case of using this method. Just play with caps values.

HTH!

EDIT:

Thought about this problem and wrote small example. I understood that resizableImageWithCapInsets: can save only corners of image in case we use two dimension scale.

I see 2 ways:

  1. Use two controls: one for balloon and one for arrow with proper images
  2. Render image for this one control from two images

I decided to realize second one. Pass ballonView.frame as argument here:

- (UIImage *)balloonImageWithRect:(CGRect)rect{
    //create two images, ballon image with cap corners
    UIImage *ballonImage = [[UIImage imageNamed:@"balloon"] resizableImageWithCapInsets:UIEdgeInsetsMake(IMAGE_CAP_INSET_TOP, IMAGE_CAP_INSET_LEFT, IMAGE_CAP_INSET_BOTTOM, IMAGE_CAP_INSET_RIGHT) resizingMode:UIImageResizingModeStretch];
    UIImage *arrowImage = [UIImage imageNamed:@"arrow"];

    //drawing area
    CGSize newSize = rect.size;
    UIGraphicsBeginImageContext(newSize);

    //leave some space for arrow at the bottom
    [ballonImage drawInRect:CGRectMake(0, 0, newSize.width, newSize.height - arrowImage.size.height)];
    //draw arrow at the bottom
    [arrowImage drawInRect:CGRectMake((newSize.width - arrowImage.size.width)/2, newSize.height - arrowImage.size.height, arrowImage.size.width, arrowImage.size.height)];

    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return newImage;
}

Then we just set this image to our ballonView.

Also I leave gist with full code of that ViewController with random sizes of that balloon: https://gist.github.com/AlloyDev/7910637

Also you can use that two images:



回答3:

Use UIImage.h delegate method

// use resizableImageWithCapInsets: and capInsets.

- (UIImage *)stretchableImageWithLeftCapWidth:(NSInteger)leftCapWidth topCapHeight:(NSInteger)topCapHeight;
@property(nonatomic,readonly) NSInteger leftCapWidth;   // default is 0. if non-zero, horiz. stretchable. right cap is calculated as width - leftCapWidth - 1
@property(nonatomic,readonly) NSInteger topCapHeight;   // default is 0. if non-zero, vert. stretchable. bottom cap is calculated as height - topCapWidth - 1

like this

UIImage *balloon = [[UIImage imageNamed:@"grey.png"] stretchableImageWithLeftCapWidth:24 topCapHeight:15];

hope this helps.



回答4:

For the image in the question (assuming it's a Retina image):

[[UIImage imageNamed:@"Bubble"] resizableImageWithCapInsets:UIEdgeInsetsMake(14, 28, 14, 26) resizingMode:UIImageResizingModeStretch];

If the image you've provided in the question is a non-retina image, halve the values.

Modify the values (UIEdgeInsetsMake(top, left, bottom, right)) to suit any image you need.