Search code examples
iosobjective-cuiimageresizable

Resizable UIImage


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


Solution

  • 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