Подтвердить что ты не робот

Подкласс iOS UIView, нарисуйте сквозной текст на фоне

Я хочу нарисовать текст в моем подклассе на UIView, чтобы текст был вырезан из формы, а фон за просмотром показан, как и в логотипе OSX Mavericks, найденном .

Я бы сказал, что я уже являюсь промежуточным/ранним продвинутым разработчиком iOS, поэтому не стесняйтесь бросать какие-то сумасшедшие решения. Я бы ожидал, что мне придется переопределить drawRect, чтобы сделать это.

Спасибо, ребята!

EDIT:

Я должен упомянуть, что моя первая попытка заключалась в том, что текст [UIColor clearColor] не работал, так как это просто установило альфа-компонент текста в 0, что только показало представление через текст.

4b9b3361

Ответ 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]. Не уверен, что это абсолютно необходимо или нет.

Я уверен, что у этого есть некоторые опечатки, но могу вас заверить, проверенная проверка заклинаний работает нормально.