I would like to achieve the same effect as in the new iTunes remote update for iOS 7 for my UILabel
.
If you look at this screen:
(The one on the right) you'll notice that the UILabel
text color is the background blurred album cover without the black mask.
At the moment I have transparent UILabel
textColor (http://cl.ly/SInK), my code is similar to https://github.com/robinsenior/RSMaskedLabel
My first assumption is to have a view hierarchy like that
UIImageView (Light blurred image)
|
UIImageView/UIView (Dark blurred image or just a dark mask for the superview)
|
UILabel (And all my other view).
I would like the UILabel
to have a transparent text color on the first UIImageView, ignoring the second one/Mask).
I can't wrap my head around a solution to achieve this effect.
Since iOS 8 Apple offer a new class, UIVibrancyEffect, which can be added to a UIVisualEffectView. This combined with a UIBlurEffect can achieve the exact same result as my screenshot above.
Source: https://developer.apple.com/library/prerelease/ios/documentation/UIKit/Reference/UIVibrancyEffect/index.html
I don't think you're going to be able to directly do this with a UILabel. What I did was decompose it into several pieces:
How to draw only the background of a label. For this I cribbed code from CGPathRef from string to turn the string into a path. Then the subclassing UILabel and adding the following drawRect did the appropriate thing.
-(void)drawRect:(CGRect)rect {
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextSaveGState(ctx);
// Convert the attributed text to a UIBezierPath
CGPathRef path = [self.attributedText createPath];
// Adjust the path bounds horizontally as requested by the view
CGRect bounds = [self textRectForBounds:rect limitedToNumberOfLines:self.numberOfLines];
CGAffineTransform xform = CGAffineTransformMakeTranslation(bounds.origin.x, bounds.origin.y);
// Adjust the path bounds vertically because it doesn't seem to be taken into account yet
bounds = CGPathGetBoundingBox(path);
xform = CGAffineTransformTranslate(xform, 0., (self.bounds.size.height - bounds.size.height) / 2.);
// Apply the transform to the path
path = CGPathCreateCopyByTransformingPath(path, &xform);
// Set colors, the fill color should be the background color because we're going
// to draw everything BUT the text, the text will be left clear.
CGContextSetFillColorWithColor(ctx, self.textColor.CGColor);
// Flip and offset things
CGContextScaleCTM(ctx, 1., -1.);
CGContextTranslateCTM(ctx, 0., 0. - self.bounds.size.height);
// Invert the path
CGContextAddRect(ctx, self.bounds);
CGContextAddPath(ctx, path);
CGContextDrawPath(ctx, kCGPathEOFill);
// Discard the path
CFRelease(path);
// Restore gstate
CGContextRestoreGState(ctx);
}
If you create a UILabel in interface builder, set the class, set the background color to clear and the foreground color to your proposed fill color, the background will show through where the text is.
To blur the body showing through the label, I dropped an FXBlurView (https://github.com/nicklockwood/FXBlurView) under the label with sizing constraints to keep them aligned.
You can see it all working here https://github.com/dwb357/TransparentLabel.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With