UIView drawRect drawing lines of wrong width

almosnow picture almosnow · Sep 7, 2010 · Viewed 12.4k times · Source

I'm trying to add a little red line on the bottom of my UIView.

I want the line to be a 1px line.

Can someone tell me why the following code:

- (void)drawRect:(CGRect)rect {
CGContextRef currentContext = UIGraphicsGetCurrentContext();
CGContextSaveGState(currentContext);
CGContextSetRGBFillColor(currentContext, 0.0f, 0.0f, 0.0f, 1.0f);
CGContextFillRect(currentContext, RECT(0, 0, rect.size.width, rect.size.height - 8));
CGContextSetLineWidth(currentContext, 1);
CGContextSetRGBStrokeColor(currentContext, 1.0f, 0.0f, 0.0f, 1.0f);
CGContextBeginPath(currentContext);
CGContextMoveToPoint(currentContext, 0, rect.size.height - 7);
CGContextAddLineToPoint(currentContext, rect.size.width, rect.size.height - 7);
CGContextStrokePath(currentContext);
CGContextRestoreGState(currentContext);
}

Draws a line that spans 2px in height?

Answer

David M. picture David M. · Sep 7, 2010

The integral coordinates indicate places half-way between pixels; that is, (0,0) is in the upper-left corner, above and to the left of the upper-left pixel; similarly, (1,0) is between the first and second pixels; finally, (0.5,0.5) is at the center of the upper-left pixel.

According to the documentation for CGContextSetLineWidth, "when stroked, the line straddles the path, with half of the total width on either side." Thus, if the path is lying precisely in between the pixels, the line will be stroked half on one row of pixels, half on the other.

Hence, to get a sharp pixel line, you must offset your coordinates by half a pixel: for your x coordinate, use rect.size.height - 7.5 instead of - 7.

By the way, when drawing rectangles, it is handy to use CGRectInset(rect, 0.5, 0.5) to achieve this.