Skip to content

Instantly share code, notes, and snippets.

@steipete
Created December 17, 2011 10:00
Show Gist options
  • Save steipete/1489839 to your computer and use it in GitHub Desktop.
Save steipete/1489839 to your computer and use it in GitHub Desktop.
DrawInsetBeveledRoundedRect
void DrawInsetBeveledRoundedRect( CGContextRef context, CGRect rect, CGFloat radius, UIColor *fillColor )
{
//contract the bounds of the rectangle in to account for the stroke
CGRect drawRect = CGRectInset(rect, 1.0f, 1.0f);
//contract the height by 1 to account for the white bevel at the bottom
drawRect.size.height -= 1.0f;
//Save the current state so we don't persist anything beyond this operation
CGContextSaveGState(context);
//Generate the rounded rectangle paths
CGPathRef boxPath = [[UIBezierPath bezierPathWithRoundedRect: drawRect cornerRadius: radius] CGPath];
//For the stroke, offset by half a pixel to ensure proper drawing
CGPathRef strokePath = [[UIBezierPath bezierPathWithRoundedRect: CGRectInset(drawRect, -0.5f, -0.5f) cornerRadius: radius] CGPath];
/*Draw the bevel effect*/
CGContextSaveGState(context);
//Set the color to be slightly transparent white
CGContextSetFillColorWithColor(context, [[UIColor colorWithWhite: 1.0f alpha: 0.8f] CGColor]);
//Clip the region to only the visible portion to optimzie drawing
CGContextClipToRect(context, CGRectMake(rect.origin.x, rect.origin.y+rect.size.height-radius, rect.size.width, radius));
//draw the left corner curve
CGRect corner = CGRectMake(rect.origin.x, (rect.origin.y+rect.size.height)-(2*radius)-1, (radius*2)+1, (radius*2)+1);
CGContextFillEllipseInRect(context, corner);
//draw the right corner
corner.origin.x = rect.origin.x + rect.size.width - (radius*2)-1;
CGContextFillEllipseInRect(context, corner);
//draw the rectangle in the middle
//set the blend mode to replace any existing pixels (or else we'll see visible overlap)
CGContextSetBlendMode(context, kCGBlendModeCopy);
CGContextFillRect(context, CGRectMake(rect.origin.x+radius, rect.origin.y+rect.size.height-radius, rect.size.width-(2*radius),radius+1));
CGContextRestoreGState(context);
/*Draw the main region */
CGContextSaveGState(context);
//fill it with our colour of choice
CGContextSetFillColorWithColor(context, [fillColor CGColor]);
//use the stroke path so the boundaries line up with the stroke (else we'll see a gap on retina devices)
CGContextAddPath(context, strokePath);
//fill it
CGContextFillPath(context);
CGContextRestoreGState(context);
/*Main fill region inner drop shadow*/
/*(This is done by duplicating the path, offsetting the duplicate by 1 pixel, and using the EO winding fill rule to fill the gap between the two)*/
CGContextSaveGState(context);
//set the colour to be a VERY faint grey
CGContextSetFillColorWithColor(context, [[UIColor colorWithWhite: 0.0f alpha: 0.08f] CGColor]);
//clip the shadow to the top of the box (to reduce overhead)
CGContextClipToRect(context, CGRectMake( drawRect.origin.x, drawRect.origin.y, drawRect.size.width, radius ));
//add the first instance of the path
CGContextAddPath(context, boxPath);
//translate the draw origin down by 1 pixel
CGContextTranslateCTM(context, 0.0f, 1.0f);
//add the second instance of the path
CGContextAddPath(context, boxPath);
//use the EO winding rule to fill the gap between the two paths
CGContextEOFillPath(context);
CGContextRestoreGState(context);
/*Outer Stroke*/
/*This is drawn outside of the fill region to prevent the fill region bleeding over in some cases*/
CGContextSaveGState(context);
//set the line width to be 1 pixel
CGContextSetLineWidth(context, 1.0f);
//set the the colour to be a very transparent shade of grey
CGContextSetStrokeColorWithColor(context, [[UIColor colorWithWhite: 0.0f alpha: 0.18f] CGColor]);
//set up the path to draw the stroke along
CGContextAddPath(context, strokePath);
//set the blending mode to replace underlying pixels on this layer (so the background will come through through)
CGContextSetBlendMode(context, kCGBlendModeCopy);
//draw the path
CGContextStrokePath(context);
CGContextRestoreGState( context );
//Restore the previous CG state
CGContextRestoreGState( context );
}
@bithavoc
Copy link

bithavoc commented Jun 7, 2013

+1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment