Подкласс iOS UIView, нарисуйте сквозной текст на фоне
Я хочу нарисовать текст в моем подклассе на UIView, чтобы текст был вырезан из формы, а фон за просмотром показан, как и в логотипе OSX Mavericks, найденном .
Я бы сказал, что я уже являюсь промежуточным/ранним продвинутым разработчиком iOS, поэтому не стесняйтесь бросать какие-то сумасшедшие решения. Я бы ожидал, что мне придется переопределить drawRect
, чтобы сделать это.
Спасибо, ребята!
EDIT:
Я должен упомянуть, что моя первая попытка заключалась в том, что текст [UIColor clearColor]
не работал, так как это просто установило альфа-компонент текста в 0, что только показало представление через текст.
Ответы
Ответ 1
Отказ от ответственности: я пишу это без тестирования, поэтому простите меня, если я ошибаюсь.
Вы должны достичь того, что вам нужно, двумя этими шагами:
-
Создайте CATextLayer
с размером вашего представления, установите backgroundColor
полностью прозрачным и foregroundColor
непрозрачным (через [UIColor colorWithWhite:0 alpha:1]
и [UIColor colorWithWhite:0 alpha:0]
). Затем установите string
свойство для строки, которую вы хотите отобразить, font
и fontSize
и т.д.
-
Установите маску слоя вида на этот слой: myView.layer.mask = textLayer
. Вам нужно будет импортировать QuartzCore
для доступа к CALayer
вашего представления.
Обратите внимание, что на первом этапе я переключался между непрозрачным и прозрачным цветом.
Изменить: Действительно, Ной был прав. Чтобы преодолеть это, я использовал CoreGraphics с режимом наложения 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
После добавления этого в контроллер просмотра вы увидите представление < <2 → , где Hello!
нарисовано.
Почему это работает:
Режим смешивания определяется как R = D*(1 - Sa)
, то есть нам нужны противоположные альфа-значения, чем в слое mask
, который я предложил ранее. Поэтому все, что вам нужно сделать, это рисовать с непрозрачным цветом, и это будет вычтено из материала, который вы нарисовали заранее.
Ответ 2
Я действительно понял, как это сделать по своему усмотрению, но ответ @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]
. Не уверен, что это абсолютно необходимо или нет.
Я уверен, что у этого есть некоторые опечатки, но могу вас заверить, проверенная проверка заклинаний работает нормально.