UIView CGGradient 剪辑到绘制的“框架”
Posted
技术标签:
【中文标题】UIView CGGradient 剪辑到绘制的“框架”【英文标题】:UIView CGGradient clipped to drawn "frame" 【发布时间】:2010-10-03 07:25:32 【问题描述】:我正在尝试绘制更复杂的 UILabel(或 UIView,如果需要,将 UILabel 放在顶部)背景。因为我希望它在用户更改 iPhone 方向时自动调整大小,所以我试图在子类 drawRect 函数中实现它。如果可能的话,我希望能够在代码中调整这一切,省略图案图像的需要。
我从之前关于这个主题的一些帖子中得到了一些提示:
Gradients on UIView and UILabels On iPhone 和 Make Background of UIView a Gradient Without Sub Classing
不幸的是,他们都错过了目标,因为我想将渐变与自定义绘图结合起来。我希望 CGGradient 被我正在绘制的线框剪裁(在圆角处可见),但我无法做到这一点。
另一种选择是使用 CAGradientLayer,它似乎工作得很好,但这需要在旋转时对框架进行一些调整,并且无论我如何尝试,渐变层似乎都绘制在文本之上。
我的问题是双重的
如何修改下面的代码,使渐变剪辑到绘制的“框架” 如何让 CAGradientLayer 在 UILabel 的文本后面绘制(或者我必须在 UILabel 后面放置一个 UIView,并以 CAGradientLayer 作为背景)这是我的drawrect函数:
- (void)drawRect:(CGRect)rect
// Drawing code
CGContextRef c = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(c, [[UIColor clearColor] CGColor]);
CGContextSetStrokeColorWithColor(c, [strokeColor CGColor]);
CGContextSetLineWidth(c, 1);
CGFloat minx = CGRectGetMinX(rect), midx = CGRectGetMidX(rect), maxx = CGRectGetMaxX(rect) ;
CGFloat miny = CGRectGetMinY(rect), midy = CGRectGetMidY(rect), maxy = CGRectGetMaxY(rect) ;
minx = minx + 1;
miny = miny + 1;
maxx = maxx - 1;
maxy = maxy - 1;
CGGradientRef glossGradient;
CGColorSpaceRef rgbColorspace;
size_t num_locations = 2;
CGFloat locations[2] = 0.0, 1.0 ;
CGFloat components[8] = 0.6, 0.6, 0.6, 1.0, // Start color
0.3, 0.3, 0.3, 1.0 ; // End color
rgbColorspace = CGColorSpaceCreateDeviceRGB();
glossGradient = CGGradientCreateWithColorComponents(rgbColorspace, components, locations, num_locations);
CGRect currentBounds = [self bounds];
CGPoint topCenter = CGPointMake(CGRectGetMidX(currentBounds), 0.0f);
CGPoint midCenter = CGPointMake(CGRectGetMidX(currentBounds), CGRectGetMidY(currentBounds));
CGPoint lowCenter = CGPointMake(CGRectGetMidX(currentBounds), CGRectGetMidY(currentBounds));
CGContextDrawLinearGradient(c, glossGradient, topCenter, midCenter, 0);
CGGradientRelease(glossGradient);
CGColorSpaceRelease(rgbColorspace);
CGContextMoveToPoint(c, minx, midy);
CGContextAddArcToPoint(c, minx, miny, midx, miny, ROUND_SIZE_INFO);
CGContextAddArcToPoint(c, maxx, miny, maxx, midy, ROUND_SIZE_INFO);
CGContextAddArcToPoint(c, maxx, maxy, midx, maxy, ROUND_SIZE_INFO);
CGContextAddArcToPoint(c, minx, maxy, minx, midy, ROUND_SIZE_INFO);
// Close the path
CGContextClosePath(c);
// Fill & stroke the path
CGContextDrawPath(c, kCGPathFillStroke);
// return;
[super drawRect: rect];
【问题讨论】:
基本上,我想知道是否有办法将 Gradient 限制在某个边界,有点像 CALayer 的 maskToBounds 标志。 使用 CAGradientLayer 似乎足以解决简单的矩形渐变背景,但问题仍然存在,是否可以使用自定义绘图完成相同的任务......(例如,如果我想绘制自定义使用 CGContextAddLineToPoint() 和 CGContextAddArcToPoint() 使用非方形边框的边框背景。是否可以使用渐变填充边框的内容以及如何实现)? 【参考方案1】:你要找的是 CGContextClip()
在代码中创建路径和渐变,然后
CGContextClip(c);
CGContextDrawLinearGradient(c, glossGradient, topCenter, midCenter, 0);
CGGradientRelease(glossGradient);
(删除您对 CGContextDrawLinearGradient 的旧调用)
还记得在您进行任何剪辑之前和之后保存和恢复您的上下文
如果您的剪辑与您想要的相反,请尝试 CGContextEOClip()(或以相反的顺序绘制路径)
【讨论】:
谢谢,我会尽快调查的! 我回到这个话题。已经有一段时间了,我希望你能读到这篇文章。我设法根据路径创建了一个具有剪裁边界的渐变,但我仍然有一个我无法解决的问题。在上面的代码中,我创建了一个圆角矩形的路径。在原始绘图中,这导致了一个带有绘制边界和另一种填充颜色的图形。现在我想为这个形状添加一个自定义渐变。问题是,您的修复要么让我用上面未剪裁的渐变绘制原始形状,要么只将渐变剪裁到路径。那么我该如何实现这两者呢? 我解决了。解决方案是在第一条路径被击中后绘制一条新路径。非常感谢!以上是关于UIView CGGradient 剪辑到绘制的“框架”的主要内容,如果未能解决你的问题,请参考以下文章
iOS Quartz2D 渐变图形 CGGradient CGShading