title: Draw a rounded UIView with gradient and drop shadow
body: <p><strong>EDIT:</strong></p>
  
  <p>I finally found a real simple solution to this problem, using the <a href="http://developer.apple.com/library/ios/#documentation/GraphicsImaging/Reference/CAGradientLayer_class/Reference/Reference.html" rel="nofollow noreferrer">CAGradientLayer</a> class, and the CALayer drawing functionalities.<br />
  Ole Begemann released a great UIView wrapper for CAGradientLayer class named <a href="https://github.com/ole/OBGradientView" rel="nofollow noreferrer">OBGradientView</a>.<br />
  This class allows you to easily create a gradient UIView in your application.<br />
  You then use the <a href="http://developer.apple.com/library/mac/#documentation/GraphicsImaging/Reference/CALayer_class/Introduction/Introduction.html" rel="nofollow noreferrer">CALayer</a> drawing functionalities to add the rounded corners and drop shadow values :</p>
  
  <pre><code>// Create the gradient view
  OBGradientView *gradient = [[OBGradientView alloc] initWithFrame:someRect];
  NSArray *colors = [NSArray arrayWithObjects:[UIColor redColor], [UIColor yellowColor], nil];
  gradient.colors = colors;
  
  // Set rounded corners and drop shadow
  gradient.layer.cornerRadius = 5.0;
  gradient.layer.shadowColor = [UIColor grayColor].CGColor;
  gradient.layer.shadowOpacity = 1.0;
  gradient.layer.shadowOffset = CGSizeMake(2.0, 2.0);
  gradient.layer.shadowRadius = 3.0;
  
  [self.view addSubview:gradient];
  [gradient release];
  </code></pre>
  
  <p>Dont forget to add the QuartzCore framework to your project.</p>
  
  <p><br />
  <br />
  <strong>ORIGINAL QUESTION:</strong></p>
  
  <p>I have been working on a custom control that is a rounded rectangle button, filled with a linear gradient, and having a drop shadow.
  I have filled the two first steps using this answer : <a href="https://stackoverflow.com/questions/1903370/rounded-rect-with-gradient-color">link text</a></p>
  
  <p>My problem is now to add a drop shadow under the resulting shape.
  Actually, the context has been clipped to the rounded rect path, so when I use the CGContextSetShadow function, it doesn't draw it.</p>
  
  <p>I tried to solve this problem by drawing the rounded rect twice, first with a plain color, so it draws the shadow, and then redraw it with the gradient fill.</p>
  
  <p>It kinda worked, but I still can see a few pixels at the corners of the shape resulting from the first draw with a plain color, as you can see on this zoomed version :</p>
  
  <p><a href="http://img269.imageshack.us/img269/6489/capturedcran20100701192.png" rel="nofollow noreferrer">http://img269.imageshack.us/img269/6489/capturedcran20100701192.png</a></p>
  
  <p>It is almost good, but not perfect yet...</p>
  
  <p>Here is my -drawRect: implementation :</p>
  
  <pre><code>static void addRoundedRectToPath(CGContextRef context, CGRect rect, float ovalWidth, float ovalHeight)
  {
   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, 1);
   CGContextAddArcToPoint(context, 0, fh, 0, fh/2, 1);
   CGContextAddArcToPoint(context, 0, 0, fw/2, 0, 1);
   CGContextAddArcToPoint(context, fw, 0, fw, fh/2, 1);
   CGContextClosePath(context);
   CGContextRestoreGState(context);
  }
  
  
  - (void)drawRect:(CGRect)rect
  { 
   CGContextRef context = UIGraphicsGetCurrentContext();
  
   CGSize shadowOffset = CGSizeMake(10.0, 10.0);
   CGFloat blur = 5.0;
  
   rect.size.width -= shadowOffset.width + blur;
   rect.size.height -= shadowOffset.height + blur;
  
   CGContextSaveGState(context);
   addRoundedRectToPath(context, rect, _radius, _radius);
   CGContextSetShadow (context, shadowOffset, blur);
   CGContextDrawPath(context, kCGPathFill);
   CGContextRestoreGState(context);
  
   addRoundedRectToPath(context, rect, _radius, _radius);
      CGContextClip(context);
  
   CGFloat colors[] =
   {
    _gradientStartColor.red, _gradientStartColor.green, _gradientStartColor.blue, _gradientStartColor.alpha,
    _gradientEndColor.red, _gradientEndColor.green, _gradientEndColor.blue, _gradientEndColor.alpha
   };
   size_t num_locations = 2;
      CGFloat locations[2] = { 0.0, 1.0 };
  
   CGColorSpaceRef rgb = CGColorSpaceCreateDeviceRGB();
   CGGradientRef gradient = CGGradientCreateWithColorComponents(rgb, colors, locations, num_locations);
  
   CGRect currentBounds = self.bounds;
   CGPoint gStartPoint = CGPointMake(CGRectGetMidX(currentBounds), 0.0f);
   CGPoint gEndPoint = CGPointMake(CGRectGetMidX(currentBounds), CGRectGetMaxY(currentBounds));
   CGContextDrawLinearGradient(context, gradient, gStartPoint, gEndPoint, 0);
  
   CGColorSpaceRelease(rgb);
   CGGradientRelease(gradient);
  }
  </code></pre>
  
  <p>Any ideas on how to do this in another way ?</p>
  
  <p>Thanks !</p>