views:

459

answers:

2

I am creating my own UITableViewCells with a gradient background. I have all the logic and drawing worked out, but one thing I want to fix is the "chunkiness" around the corners of my custom cell:

alt text

If you zoom in on the corners, you can see what I am talking about. Here is the code I a using to generate the cell:

CGContextRef c = UIGraphicsGetCurrentContext();
CGColorSpaceRef myColorspace = CGColorSpaceCreateDeviceRGB();
CGGradientRef myGradient = nil;
CGFloat components[8] = TABLE_CELL_BACKGROUND;
CGContextSetStrokeColorWithColor(c, [[UAColor colorWithWhite:0.7 alpha:1] CGColor]);
CGContextSetLineWidth(c, 2);
CGContextSetAllowsAntialiasing(c, YES);
CGContextSetShouldAntialias(c, YES);
CGFloat minx = CGRectGetMinX(rect) , midx = CGRectGetMidX(rect), maxx = CGRectGetMaxX(rect) ;
CGFloat miny = CGRectGetMinY(rect) , maxy = CGRectGetMaxY(rect) ;

CGMutablePathRef path = CGPathCreateMutable();
CGPathMoveToPoint(path, NULL, minx, miny);
CGPathAddArcToPoint(path, NULL, minx, maxy, midx, maxy, kDefaultMargin);
CGPathAddArcToPoint(path, NULL, maxx, maxy, maxx, miny, kDefaultMargin);
CGPathAddLineToPoint(path, NULL, maxx, miny);
CGPathAddLineToPoint(path, NULL, minx, miny);
CGPathCloseSubpath(path);

// Fill and stroke the path
CGContextSaveGState(c);
CGContextAddPath(c, path);
CGContextClip(c);

CGFloat locations[2] = { 0.0, 1.0 };
CGFloat mycomponents[8] = TABLE_CELL_BACKGROUND;
CGColorSpaceRef myColorspace = CGColorSpaceCreateDeviceRGB();
myGradient = CGGradientCreateWithColorComponents(myColorspace, mycomponents, locations, 2);
CGContextDrawLinearGradient(c, myGradient, CGPointMake(minx,miny), CGPointMake(minx,maxy), 0);

CGContextRestoreGState(c);  
CGContextAddPath(c, path);
CGContextStrokePath(c);

What can I do to smooth the edges while keeping a consistent edge thickness across all cells?

+2  A: 

Your line width is set to 2 points. What's happening is that your code is calculating your bounding rect without understanding the width of the line. The result is that for every straight segment of your shape, only half of the stroke's width is visible. On the arc, the full stroke width is visible.

Here's the relevant segment of code from my app, Funversation, to draw the playing cards with rounded corners similar to what you have.

CGRect rect = [self bounds];
rect.size.width -= lineWidth;
rect.size.height -= lineWidth;
rect.origin.x += lineWidth / 2.0;
rect.origin.y += lineWidth / 2.0;

Add that before your calculation for minx, midx, maxx, etc. and the strokes for your shape should be uniform.

Giao
This method was smoother than Peter's method: http://grab.by/2836
coneybeare
+1  A: 

The other way to make the stroke consistent would be to move the AddPath and StrokePath calls up above the RestoreGState call—that is, stroke while clipped.

For a truly 2-pt-wide stroke with this solution, simply double the line width you put in the graphics state (i.e., set it to 4 pt), since half of it will be clipped out.

Peter Hosey
This worked, but it was not as smooth as Giao's method http://grab.by/2832
coneybeare