Search code examples
uilabeldrawrectcgcontext

drawRect drawing 'transparent' text?


I am looking to draw a UILabel (preferable through subclassing) as a transparent label, but with solid background. I draw up an quick example (sorry, it's ugly, but it gets the points across :)).

Basically I have a UILabel and I would like the background to be a set colour, and the text should be transparent. I do not want to colour the text with the views background, but instead have it be 100% transparent, since I have a texture in the background that I want to make sure lines up inside and outside of the label.

I've been spending the night browsing SO and searching on Google, but I have found no helpful sources. I don't have much experience with CG drawing, so I would appreciate any links, help, tutorial or sample code (maybe Apple has some I need to have a look at?).

Thanks a bunch!

enter image description here


Solution

  • I've rewritten it as a UILabel subclass using barely any code and posted it on GitHub

    The gist of it is you override drawRect but call [super drawRect:rect] to let the UILabel render as normal. Using a white label color lets you easily use the label itself as a mask.

    - (void)drawRect:(CGRect)rect
    {
        CGContextRef context = UIGraphicsGetCurrentContext();
    
        // let the superclass draw the label normally
        [super drawRect:rect];
    
        CGContextConcatCTM(context, CGAffineTransformMake(1, 0, 0, -1, 0, CGRectGetHeight(rect)));
    
        // create a mask from the normally rendered text
        CGImageRef image = CGBitmapContextCreateImage(context);
        CGImageRef mask = CGImageMaskCreate(CGImageGetWidth(image), CGImageGetHeight(image), CGImageGetBitsPerComponent(image), CGImageGetBitsPerPixel(image), CGImageGetBytesPerRow(image), CGImageGetDataProvider(image), CGImageGetDecode(image), CGImageGetShouldInterpolate(image));
    
        CFRelease(image); image = NULL;
    
        // wipe the slate clean
        CGContextClearRect(context, rect);
    
        CGContextSaveGState(context);
        CGContextClipToMask(context, rect, mask);
    
        CFRelease(mask);  mask = NULL;
    
        [self RS_drawBackgroundInRect:rect];
    
        CGContextRestoreGState(context);
    
    }