我想在UIView上的子类上绘制文本,以便文本从形状中剪切出来,视图后面的背景显示出来,就像在OSX Mavericks logo中找到here一样。
我会说我更像是一个中级/早期的高级iOS开发人员,所以请随意向我提出一些疯狂的解决方案。我希望我必须覆盖drawRect
才能做到这一点。
谢谢你们!
编辑:
我应该提一下,我的第一次尝试是使文本[UIColor clearColor]
无效,因为只是将文本的alpha分量设置为0,这只是通过文本显示视图。
答案 0 :(得分:18)
免责声明:我是在没有经过测试的情况下写的,所以如果我在这里错了,请原谅我。
您应该通过以下两个步骤实现所需:
根据视图大小创建CATextLayer
,将backgroundColor
设置为完全透明,将foregroundColor
设置为不透明([UIColor colorWithWhite:0 alpha:1]
和{{ 1}}。然后将[UIColor colorWithWhite:0 alpha:0]
属性设置为您要呈现的字符串,string
和font
等。
将视图的图层蒙版设置为此图层:fontSize
。您必须导入myView.layer.mask = textLayer
才能访问视图的QuartzCore
。
请注意,我可能会在第一步中在不透明和透明颜色之间切换。
编辑:确实,诺亚是对的。为了解决这个问题,我使用CoreGraphics和CALayer
混合模式。
首先,示例视图显示它确实有效:
kCGBlendModeDestinationOut
将此添加到视图控制器后,您会看到@implementation TestView
- (id)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
self.backgroundColor = [UIColor clearColor];
}
return self;
}
- (void)drawRect:(CGRect)rect {
[[UIColor redColor] setFill];
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:self.bounds cornerRadius:10];
[path fill];
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSaveGState(context); {
CGContextSetBlendMode(context, kCGBlendModeDestinationOut);
[@"Hello!" drawAtPoint:CGPointZero withFont:[UIFont systemFontOfSize:24]];
} CGContextRestoreGState(context);
}
@end
后面的视图,其中TestView
已被绘制。
为什么这样做:
混合模式定义为Hello!
,这意味着我们需要与之前建议的R = D*(1 - Sa)
层相反的alpha值。因此,您需要做的就是使用不透明的颜色进行绘制,这将从您事先在视图上绘制的内容中减去。
答案 1 :(得分:1)
我实际上已经想出了如何自己做到这一点,但@ StatusReport的答案是完全有效的,并且现在正常运作。
我是这样做的:
-(void)drawRect:(CGRect)rect{
CGContextRef context = UIGraphicsGetCurrentContext();
[[UIColor darkGrayColor]setFill]; //this becomes the color of the alpha mask
CGContextFillRect(context, rect);
CGContextSaveState(context);
[[UIColor whiteColor]setFill];
//Have to flip the context since core graphics is done in cartesian coordinates
CGContextTranslateCTM(context, 0, rect.size.height);
CGContextScaleCTM(context, 1.0, -1.0);
[textToDraw drawInRect:rect withFont:[UIFont fontWithName:@"HelveticaNeue-Thin" size:40];
CGContextRestoreGState(context);
CGImageRef alphaMask = CGBitmapContextCreateImage(context);
[[UIColor whiteColor]setFill];
CGContextFillRect(context, rect);
CGContextSaveGState(context);
CGContentClipToMask(context, rect, alphaMask);
[backgroundImage drawInRect:rect];
CGContextRestoreGState(context);
CGImageRelease(alphaMask);
}
- (void)setTextToDraw:(NSString*)text{
if(text != textToDraw){
textToDraw = text;
[self setNeedsDisplay];
}
}
我有@synthesize
textToDraw
声明,因此我可以覆盖设置者并调用[self setNeedsDisplay]
。不确定这是否完全必要。
我确定这有一些错别字但是我可以向你保证,拼写检查的版本运行得很好。
答案 2 :(得分:1)
StatusReport接受的答案写得很漂亮,因为我还没有找到这个问题的Swift答案,所以我认为我会将他的答案用作Swift版本的模板。我通过允许将字符串作为视图的参数输入来提醒人们,可以使用视图的所有属性(角半径,颜色等)来完成视图的添加,从而为视图增加了一点可扩展性可扩展的。显然,框架在初始化器中被清零了,因为在使用视图时应该将约束应用于视图。
快捷键4
class CustomView: UIView {
var title: String
init(title: String) {
self.title = title
super.init(frame: CGRect.zero)
config()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func config() {
backgroundColor = UIColor.clear
}
override func draw(_ rect: CGRect) { // do not call super
UIColor.red.setFill()
let path = UIBezierPath(roundedRect: bounds, cornerRadius: 10)
path.fill()
weak var context = UIGraphicsGetCurrentContext() // Apple wants this to be weak
context?.saveGState()
context?.setBlendMode(CGBlendMode.destinationOut)
title.draw(at: CGPoint.zero, withAttributes: [NSAttributedString.Key.font : UIFont.systemFont(ofSize: 24)])
context?.restoreGState()
}
}
let customView = CustomView(title: "great success")