How to create a flexible photo frame on iPhone?

I am trying to create a flexible frame for my iPhone application with small images. CustomView inherits from UIView and overrides its setFrame: In setFrame :, I'm trying to call [self setNeedsDisplay]; . Every time I scale a photo, this frame really displays and changes, but something does not work very well. Code and effect below:

This is the image that I used to draw the frame, in code for self.patternImage


Effect of my code


Effect of my code


// rotate to get a mirror image of the image source, and isHorization means the direction of rotation - (UIImage *) fetchMirrorImage: (UIImage *) originImage direction: (BOOL) isHorization {CGSize imageSize = originImage.size; UIGraphicsBeginImageContext (IMAGESIZE); CGContextRef context = UIGraphicsGetCurrentContext (); CGAffineTransform transform = CGAffineTransformIdentity;

  if (isHorization) { transform = CGAffineTransformMakeTranslation(imageSize.width, 0.0); transform = CGAffineTransformScale(transform, -1.0, 1.0); }else { transform = CGAffineTransformMakeTranslation(0.0, imageSize.height); transform = CGAffineTransformScale(transform, 1.0, -1.0); } CGContextScaleCTM(context, 1, -1); CGContextTranslateCTM(context, 0, -imageSize.height); CGContextConcatCTM(context, transform); CGContextDrawImage(context, CGRectMake(0, 0, imageSize.width, imageSize.height), originImage.CGImage); UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return newImage; } - (UIImage*)fetchPattern:(PatternType)pattern{ if (!self.patternImage) { return nil; } UIImage *tmpPattern = nil; CGRect fetchRect = CGRectZero; CGSize imageSize = self.patternImage.size; switch (pattern) { case kTopPattern: fetchRect = CGRectMake(self.insetSize.width, 0, imageSize.width-self.insetSize.width, self.insetSize.height); tmpPattern = [UIImage imageWithCGImage:CGImageCreateWithImageInRect(self.patternImage.CGImage, fetchRect)]; break; case kTopRightPattern: fetchRect = CGRectMake(0, 0, self.insetSize.width, self.insetSize.height); tmpPattern = [UIImage imageWithCGImage:CGImageCreateWithImageInRect(self.patternImage.CGImage, fetchRect)]; break; case kRightPattern: break; case kRightBottomPattern: break; case kBottomPattern: break; case kLeftBottomPattern: break; case kLeftPattern: fetchRect = CGRectMake(0, self.insetSize.height, self.insetSize.width, imageSize.height-self.insetSize.height); tmpPattern = [UIImage imageWithCGImage:CGImageCreateWithImageInRect(self.patternImage.CGImage, fetchRect)]; break; case kLeftTopPattern: fetchRect = CGRectMake(0, 0, self.insetSize.width, self.insetSize.height); tmpPattern = [UIImage imageWithCGImage:CGImageCreateWithImageInRect(self.patternImage.CGImage, fetchRect)]; break; default: break; } return tmpPattern; } // Only override drawRect: if you perform custom drawing. // An empty implementation adversely affects performance during animation. - (void)drawRect:(CGRect)rect { if (self.patternImage == nil) { return; } // Drawing code. UIImage *conLeftImage = [self fetchPattern:kLeftTopPattern]; [conLeftImage drawAtPoint:CGPointMake(0, 0)]; UIImage *topImage = [self fetchPattern:kTopPattern]; [topImage drawAsPatternInRect:CGRectMake(self.insetSize.width, 0, self.frame.size.width-self.insetSize.width*2, self.insetSize.height)]; UIImage *leftImage = [self fetchPattern:kLeftPattern]; [leftImage drawAsPatternInRect:CGRectMake(0, self.insetSize.height, self.insetSize.width, self.frame.size.height-self.insetSize.height*2)]; UIImage *conRightImage = [self fetchMirrorImage:conLeftImage direction:YES]; [conRightImage drawAtPoint:CGPointMake(self.frame.size.width-self.insetSize.width, 0)]; UIImage *rightImage = [self fetchMirrorImage:leftImage direction:YES]; CGRect rectRight = CGRectMake(self.frame.size.width-self.insetSize.width, self.insetSize.height, self.insetSize.width, self.frame.size.height-self.insetSize.height*2); [rightImage drawAsPatternInRect:rectRight]; UIImage *botRightImage = [self fetchMirrorImage:conRightImage direction:NO]; [botRightImage drawAtPoint:CGPointMake(self.frame.size.width-self.insetSize.width, self.frame.size.height-self.insetSize.height)]; UIImage *bottomImage = [self fetchMirrorImage:topImage direction:NO]; CGRect bottomRect = CGRectMake(self.insetSize.width, self.frame.size.height-self.insetSize.height, self.frame.size.width-self.insetSize.width*2, self.insetSize.height); [bottomImage drawAsPatternInRect:bottomRect]; UIImage *botLeftImage = [self fetchMirrorImage:conLeftImage direction:NO]; [botLeftImage drawAtPoint:CGPointMake(0, self.frame.size.height-self.insetSize.height)]; [super drawRect:rect]; } - (void)setFrame:(CGRect)frame{ [super setFrame:frame]; [self setNeedsDisplay]; } 
+4
source share
2 answers

Yes, I do it !!! final effect The only thing I need to do is set the phase of the current context.

 CGContextSetPatternPhase(context, CGSizeMake(x, y)); 

x, y is the starting point at which I want the template to be drawn.

I just made a mistake to use the template. If I do not set the phase of the current context, it starts filling the template to the left of the context (0,0) each time.

  CGColorRef color = NULL; UIImage *leftImage = [UIImage imageNamed:@"like_left.png"]; color = [UIColor colorWithPatternImage:leftImage].CGColor; CGContextSetFillColorWithColor(context, color); CGContextFillRect(context, CGRectMake(0, 0, FRAME_WIDTH, rect.size.height)); UIImage *topImage = [UIImage imageNamed:@"like_top.png"]; color = [UIColor colorWithPatternImage:topImage].CGColor; CGContextSetFillColorWithColor(context, color); CGContextFillRect(context, CGRectMake(0, 0, rect.size.width,FRAME_WIDTH)); UIImage *bottomImage = [UIImage imageNamed:@"like_bom.png"]; CGContextSetPatternPhase(context, CGSizeMake(0, rect.size.height - FRAME_WIDTH)); color = [UIColor colorWithPatternImage:bottomImage].CGColor; CGContextSetFillColorWithColor(context, color); CGContextFillRect(context, CGRectMake(0, rect.size.height - FRAME_WIDTH, rect.size.width, FRAME_WIDTH)); UIImage *rightImage = [UIImage imageNamed:@"like_right.png"]; CGContextSetPatternPhase(context, CGSizeMake(rect.size.width - FRAME_WIDTH, 0)); color = [UIColor colorWithPatternImage:rightImage].CGColor; CGContextSetFillColorWithColor(context, color); CGContextFillRect(context, CGRectMake(rect.size.width - FRAME_WIDTH, 0, FRAME_WIDTH, rect.size.height)); 
+4
source

First, I will say the following:
Now I have no real answer. But, I have a hint .. I think it will be useful.

According to the tutorial published by Larmarche , you can easily customize the borders of a UIView by overriding drawRect: And if you go to the comments below (on the tutorial website), you can see the following comment:

I found another glitch. When you change the borders of RoundRect, it will not be updated - so the corners sometimes get all screw (because they scale automatically).

A quick fix is ​​to add the following methods for both methods:

self.contentMode = UIViewContentModeRedraw;

Setting contentMode for Redrows saves your problem when calling setNeedsDisplay . You can easily change the frame of a UIView, instantly or animate it, and the UIView will automatically redraw.

I will try to examine your problem in more detail later. I will try to implement it.

0
source

All Articles