I'm trying to add images to table cells in a grouped UITableView but the corners of the images are not clipped. What's the best way to go about clipping these (besides clipping them in Photoshop? The table contents are dynamic.)
views:
965answers:
5There isn't a built-in standard way to do this, but it's not terribly hard to do in your own code. There are examples on how to round corners on an UIImage on the web, see for example http://blog.sallarp.com/iphone-uiimage-round-corners/.
This was my solution, which could use a little refactoring:
void addRoundedRectToPath(CGContextRef context, CGRect rect, float ovalWidth, float ovalHeight, BOOL top, BOOL bottom)
{
float fw, fh;
if (ovalWidth == 0 || ovalHeight == 0) {
CGContextAddRect(context, rect);
return;
}
CGContextSaveGState(context);
CGContextTranslateCTM (context, CGRectGetMinX(rect), CGRectGetMinY(rect));
CGContextScaleCTM (context, ovalWidth, ovalHeight);
fw = CGRectGetWidth (rect) / ovalWidth;
fh = CGRectGetHeight (rect) / ovalHeight;
CGContextMoveToPoint(context, fw, fh/2);
CGContextAddArcToPoint(context, fw, fh, fw/2, fh, 0);
NSLog(@"bottom? %d", bottom);
if (top) {
CGContextAddArcToPoint(context, 0, fh, 0, fh/2, 3);
} else {
CGContextAddArcToPoint(context, 0, fh, 0, fh/2, 0);
}
if (bottom) {
CGContextAddArcToPoint(context, 0, 0, fw/2, 0, 3);
} else {
CGContextAddArcToPoint(context, 0, 0, fw/2, 0, 0);
}
CGContextAddArcToPoint(context, fw, 0, fw, fh/2, 0);
CGContextClosePath(context);
CGContextRestoreGState(context);
}
- (UIImage *)roundCornersOfImage:(UIImage *)source roundTop:(BOOL)top roundBottom:(BOOL)bottom {
int w = source.size.width;
int h = source.size.height;
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(NULL, w, h, 8, 4 * w, colorSpace, kCGImageAlphaPremultipliedFirst);
CGContextBeginPath(context);
CGRect rect = CGRectMake(0, 0, w, h);
addRoundedRectToPath(context, rect, 4, 4, top, bottom);
CGContextClosePath(context);
CGContextClip(context);
CGContextDrawImage(context, CGRectMake(0, 0, w, h), source.CGImage);
CGImageRef imageMasked = CGBitmapContextCreateImage(context);
CGContextRelease(context);
CGColorSpaceRelease(colorSpace);
return [UIImage imageWithCGImage:imageMasked];
}
Implement those functions, then check the indexPath
in the cellForRowAtIndexPath
delegate method to determine which corner to round.
if (indexPath.row == 0) {
cell.imageView.image = [self roundCornersOfImage:coverImage roundTop:YES roundBottom:NO];
} else if (indexPath.row == [indexPath length]) {
cell.imageView.image = [self roundCornersOfImage:coverImage roundTop:NO roundBottom:YES];
} else {
cell.imageView.image = coverImage;
}
There is built-i way if you want to just display the rounded corners. Put the image in a UIImageView and then set the cornerRadius of the layer of the UIImageView. You will also need to tell the UIImageView to clip to bounds but that will give you rounded corners.
UIImageView *myImageView = [[UIImageView alloc] initWithImage:...];
[myImageView setClipsToBounds:YES];
[[myImageView layer] setCornerRadius:5.0f];
I was wondering how is the scrolling performance using addRoundedRectToPath, and QuartzCore layer property cornerRadius. Which one is better to use for good table view scrolling? Thanks, Oliver
If you're happy to have all four image corners rounded, then you can just do the following when creating the cell:
cell.imageView.layer.masksToBounds = YES;
cell.imageView.layer.cornerRadius = 10.0;
If you also want to inset the image from the boundary, I described a simple category on UIImage to do it here.