Build a UIImage with multiple stretchable images

2019-03-30 11:46发布

I have 3 images, a left cap, right cap, and center. Perhaps using CGImageRefs (?), is there a way to build a bitmap based on a CGRect that would center the center piece in some container, stretch the left cap until it reaches the center piece and the same for the right then produce a UIImage?

3条回答
三岁会撩人
2楼-- · 2019-03-30 12:12

Your is a strange approach :)

You have three different images that compose a single stretchable image but you want to build it programmatically every time you have to use it in a certain way. This waste cpu cycles. iOS framework allow you to stretch an image as you would. Open your files into your image editor (Photoshop, or something similar). Compose a single image containing the center image surrounded by the left and right cap.

Now you can use this image as every other images or you can stretch it as you would using the UIImage method

- (UIImage *)resizableImageWithCapInsets:(UIEdgeInsets)capInsets

The UIEdgeInsets is a simple struct that identify your cap limits. So supposing you have to stretch 15pt left and 20pt right you insets will be: top: 0 buttom:0 left:15 right:20

That's it.

Here for details. The article talk about a deprecated method from iOS 5.0 and above but the theory behind is the same.

查看更多
淡お忘
3楼-- · 2019-03-30 12:16

I say just do it programatically, yes it might waste a few CPU cycles but it'll be more fun.

OK, here we go...

Let's have 3 UIImageViews defined in the header

UIImageView *left;
UIImageView *center;
UIImageView *right;

In viewDidLoad we'll create them

left = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"left.jpg"]];
center = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"center.jpg"]];
right = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"right.jpg"]];


[self.view addSubview:left];
[self.view addSubview:center];
[self.view addSubview:right];

//set the position of the center piece wherever you like, whatever size is right for your arrow
[self setCenterFrame:CGRectMake(100,100,100,100)]; //we'll make this function below

then let's make a method you can use to set the position of the center image, and have the other images shimmy around into place, stretching themselves to the edges left and right.

-(void)setCenterFrame:(CGRect)rect
{
    center.frame = rect; // this is your arrow

    //set size of left
    left.frame = CGRectMake(0,rect.origin.y, rect.origin.x, rect.size.height);

    //work out how much space there is to the right
    float sizeToTheRight = (self.view.bounds.size.width - rect.size.width) - rect.origin.x ;

    //set size of right
    right.frame = CGRectMake(rect.size.width + rect.origin.x,rect.origin.y, sizeToTheRight, rect.size.height);


}
查看更多
走好不送
4楼-- · 2019-03-30 12:24

Ok I looked it up as promised. Here is a solution:

The Basic Idea

  • take the left cap and make an UIImage with stretched right side
  • "glue" it with the arrow UIImage
  • and now glue it with right cap with a left stretched side

And here is a small graphic how i think it could word

  ______ ........    ________      .........___________
 {______|........|  | arrow  |    |.........|__________)
left cap|lc flex     --------      rc flex  | right cap

The code

// get the images from disk
UIImage *leftCap = [UIImage imageNamed:@"leftCap.png"];
UIImage *arrow = [UIImage imageNamed:@"arrow.png"];
UIImage *rightCap = [UIImage imageNamed:@"rightCap"];

// stretch left and right cap
// calculate the edge insets beforehand !

UIImage *leftCapStretched = [leftCap resizableImageWithCapInsets:UIEdgeInsetsMake(topInset, leftInset, bottomInset, rightInset)];
UIImage *rightCapStretched = [rightCap resizableImageWithCapInsets:UIEdgeInsetsMake(topInset, leftInset, bottomInset, rightInset)];

CGFloat widthOfAllImages = leftCapStretched.size.width + arrow.size.width + rightCapStretched.size.width;

// build the actual glued image

UIGraphicsBeginImageContextWithOptions(CGSizeMake(widthOfAllImages, arrow.size.height), NO, 0);
[leftCapStretched drawAtPoint:CGPointMake(0, 0)];
[arrow drawAtPoint:CGPointMake(leftCap.size.width, 0)];
[rightCapStretched drawAtPoint:CGPointMake(leftCap.size.width + arrow.size.width, 0)];
UIImage* im = UIGraphicsGetImageFromCurrentImageContext(); 
UIGraphicsEndImageContext();

// now you should have a ready to use UIImage ;)

The alternative

Inspired by Jonathan Plaketts answers the same should ne possible with just UIImageViews and stretching the UIImages as above.

查看更多
登录 后发表回答