Question

I know this topic has lots of Q&A, I read them all and still couldn't get it going... I'm trying to stretch an image, while keeping its rounded edges.

This is my image (104x77px):

enter image description here

this is the code I'm using:

UIImage *bg = [UIImage imageNamed:@"btnBg"];
UIEdgeInsets insets = UIEdgeInsetsMake((bg.size.height - 1)/2, (bg.size.width - 1)/2, (bg.size.height - 1)/2, (bg.size.width - 1)/2);
bg = [bg resizableImageWithCapInsets:insets];

UIImageView *imgView = [[UIImageView alloc] initWithFrame:CGRectMake(20, 20, 50, 44)];
imgView.image = bg;

UIImageView *imgView2 = [[UIImageView alloc] initWithFrame:CGRectMake(20, 70, 250, 44)];
imgView2.image = bg;

[self.view addSubview:imgView];
[self.view addSubview:imgView2];

and this is the problem:

As you can see each image has different edges. What am I doing wrong?!

enter image description here

Was it helpful?

Solution 2

Whenever any scaling is involved, images of two different dimensions can't look quite the same. However you can break your image into three parts: the left corners, the middle section (just the parallel lines), and the right corners.

Now to create image views of different sizes, you'll keep the left and right parts constant, and scale the middle section, which won't look distorted as long as you keep the heights constant.

Note that I have give the height of fitInRect as 77 because that's the original image height. You can change this to, say, 44 but keep the number constant for all image views. Finally, widthToPreserve HAS to be a minimum of 34 (which means the overall Rect width has to be 68 or more) because that's the width of the rounded edge in the original image.

Of course, you can simply all this by having a smaller image, if your target image view height is 44.

This code works:

-(void)viewDidAppear:(BOOL)animated
{
    UIImage *img = [UIImage imageNamed:@"img"];

    UIImageView *view1 = [self getImageViewFromImage:img widthToPreserve:34 fitInRect:CGRectMake(20, 20, 100, 77)];

    UIImageView *view2 = [self getImageViewFromImage:img widthToPreserve:34 fitInRect:CGRectMake(20, 120, 250, 77)];

    [self.view addSubview:view1];
    [self.view addSubview:view2];

}

-(UIImageView*)getImageViewFromImage:(UIImage*)image widthToPreserve:(float)width fitInRect:(CGRect)rect
{
    CGImageRef left, middle, right;
    CGRect leftRect, middleRect, rightRect;
    UIImage *leftImage, *middleImage, *rightImage;
    UIImageView *leftView, *middleView, *rightView;

    // calculate CGRect values for the original image
    leftRect = CGRectMake(0, 0, width, image.size.height);
    middleRect = CGRectMake(width, 0, image.size.width - 2*width, image.size.height);
    rightRect = CGRectMake(image.size.width - width, 0, width, image.size.height);

    left = CGImageCreateWithImageInRect([image CGImage], leftRect);
    middle = CGImageCreateWithImageInRect([image CGImage], middleRect);
    right = CGImageCreateWithImageInRect([image CGImage], rightRect);


    leftImage = [UIImage imageWithCGImage:left];
    middleImage = [UIImage imageWithCGImage:middle];
    rightImage = [UIImage imageWithCGImage:right];

    leftView = [[UIImageView alloc] initWithImage:leftImage];
    middleView = [[UIImageView alloc] initWithImage:middleImage];
    rightView = [[UIImageView alloc] initWithImage:rightImage];

    //make your image subviews, with scaling on the middle view
    [leftView setFrame:CGRectMake(0, 0, width, rect.size.height)];
    [middleView setFrame:CGRectMake(width, 0, rect.size.width - 2*width, rect.size.height)];
    [rightView setFrame:CGRectMake(rect.size.width - width, 0, width, rect.size.height)];

//add your 3 subviews into a single image view
    UIImageView *imgView = [[UIImageView alloc] initWithFrame:rect];
    [imgView addSubview:leftView];
    [imgView addSubview:middleView];
    [imgView addSubview:rightView];


    CGImageRelease(left);
    CGImageRelease(middle);
    CGImageRelease(right);

    return imgView;
}

Screenshot:

enter image description here

OTHER TIPS

I think what you are looking for is a stretchable image

[[UIImage imageNamed:@"someimage.png"] stretchableImageWithLeftCapWidth:5 topCapHeight:5];

As maddy points out this is deprecated in iOS 5, for those of us poor souls having to support iOS 4.3 this is what we use.

You can specify the residing mode for your image. The choices are UIImageResizingModeStretch and UIImageResizingModeTile.

The idea of having a stretchable image is so that you can have a small image file. You should consider using a smaller image to save space in your app bundle. Also, your left and right edge insets don't have to be in the middle. They should be just beyond the curve, which looks to be about 40 points in your image.

Here's the code to use to set the resizing mode:

bg = [bg resizableImageWithCapInsets:insets resizingMode: UIImageResizingModeStretch];

Check this out: Resizable UIImage where outside stretches and inside is kept the same

Basically the opposite of what you want. Hope it helps!

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top