EDIT:
我终于找到了一个真正简单的解决方案,使用CAGradientLayer类和CALayer绘图功能 .
Ole Begemann为名为OBGradientView的CAGradientLayer类发布了一个很棒的UIView包装器 .
该类允许您在应用程序中轻松创建渐变UIView .
然后使用CALayer绘图功能添加圆角和投影值:
// 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];
别忘了将QuartzCore框架添加到您的项目中 .
ORIGINAL QUESTION:
我一直在研究一个自定义控件,它是一个圆角矩形按钮,填充线性渐变,并有一个投影 . 我使用这个答案填写了前两个步骤:link text
我现在的问题是在生成的形状下添加阴影 . 实际上,上下文已被剪切为圆角矩形路径,因此当我使用CGContextSetShadow函数时,它不会绘制它 .
我尝试通过绘制圆角矩形两次来解决这个问题,首先使用纯色,然后绘制阴影,然后使用渐变填充重绘它 .
它有点工作,但我仍然可以在第一次使用纯色绘制时看到形状角落处的几个像素,正如您在此缩放版本中看到的那样:
http://img269.imageshack.us/img269/6489/capturedcran20100701192.png
它几乎是好的,但还不完美......
这是我的-drawRect:实现:
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);
}
关于如何以另一种方式做到这一点的任何想法?
谢谢 !
4 回答
为了创建一个带有渐变背景和投影的圆角视图,这里有以下内容:
第一部分与问题中提供的非常相似,它使用CGPathAddArcToPoint创建一个圆形的rect路径,如this article中所述 . 这是帮助我理解的图片:
第二部分的工作原理如下:
在图形上下文中启用阴影,添加刚刚定义的路径,然后填充该路径 . 您可以简单地将阴影应用于渐变,因为它实际上不是标准填充(有关详细信息,请参阅this post) .
一旦你有一个填充圆角矩形创建阴影,你需要在其上方绘制渐变 . 因此,第二次添加路径以设置剪切区域,然后使用CGContextDrawLinearGradient绘制渐变 . 我认为您不能像使用早期标准填充步骤那样使用渐变轻松“填充”路径,因此请使用渐变填充绘图区域,然后剪切到您感兴趣的圆角矩形区域在 .
对于阴影,您可以使用
CGContextSetShadow()
这段代码会用阴影绘制一些东西:
我有解决方案,不需要预填充路径 . 优点(?)是阴影可以使用渐变的透明效果(即,如果渐变从不透明到透明,阴影也将部分透明)并且更简单 .
它或多或少像:
我想这是因为CGContextBeginTransparencyLayer / CGContextEndTransparencyLayer在剪辑之外并且阴影应用于该层(其包含渐变填充路径) . 至少它似乎对我有用 .
您的(原始)问题是当您绘制渐变时再次绘制阴影 . 这个阴影有一个(0,0)偏移和一点点模糊,只有角落才会闪耀 . 在CGContextDrawLinearGradient(...)之前的行中,添加以下内容:
NULL颜色值禁用阴影并将删除角落效果 .