Is it possible to draw with simple text shadows when using the NSString UIKit additions? I mean without writing code to draw twice in two colors, as can be done with various
The following snippet uses CALayer to add shadow around the edges of the characters in a UILabel:
_helloLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 320, 30)];
[_helloLabel setBackgroundColor:[UIColor clearColor]];
[_helloLabel setTextColor:[UIColor whiteColor]];
[_helloLabel setTextAlignment:NSTextAlignmentCenter];
[_helloLabel setFont:[UIFont lightApplicationFontOfSize:30]];
_helloLabel.layer.shadowColor = UIColorFromRGB(0xd04942).CGColor;
_helloLabel.layer.shadowOffset = CGSizeMake(0, 0);
_helloLabel.layer.shadowRadius = 2.0;
_helloLabel.layer.shadowOpacity = 1.0;
[self addSubview:_helloLabel];
. . normally this would add a shadow around the border, but UILabel seems to treat these properties as a special case.
A couple of thoughts:
The UITextAttributeTextShadow...
keys are intended for when using a text attribute dictionary with, for example, UIAppearance
methods:
NSDictionary *attributes = @{UITextAttributeTextShadowColor : [UIColor blackColor],
UITextAttributeTextShadowOffset : [NSValue valueWithUIOffset:UIOffsetMake(2.0, 0.0)],
UITextAttributeTextColor : [UIColor yellowColor]};
[[UINavigationBar appearance] setTitleTextAttributes:attributes];
The UITextAttributeTextShadow...
keys are designed for use only in those methods that accept a text attributes dictionary.
The closest equivalent key when drawing text strings is the use of attributed strings with the NSShadowAttributeName
key:
- (void)drawRect:(CGRect)rect
{
UIFont *font = [UIFont systemFontOfSize:50];
NSShadow *shadow = [[NSShadow alloc] init];
shadow.shadowColor = [UIColor blackColor];
shadow.shadowBlurRadius = 0.0;
shadow.shadowOffset = CGSizeMake(0.0, 2.0);
NSDictionary *attributes = @{NSShadowAttributeName : shadow,
NSForegroundColorAttributeName : [UIColor yellowColor],
NSFontAttributeName : font};
NSAttributedString *attributedText = [[NSAttributedString alloc] initWithString:@"this has shadows" attributes:attributes];
[attributedText drawInRect:rect];
}
If you're concerned about the performance hit of a shadow algorithm capable of doing a bezier curve shadow, though, NSShadow
may suffer from that. But doing some benchmarks, changing the shadowBlurRadius
dramatically affects performance. For example, animating the rotation of a complex multi-line text with a shadowBlurRadius
of 10.0
on a slow iPhone 3GS achieved a frame rate of 31 fps, but changing shadowBlurRadius
to 0.0
yielded a frame rate of 60 fps.
Bottom line, using a shadow blur radius of 0.0
eliminates most (if not all) of the computational overhead of a bezier generated shadow.
FYI, I experience a similar performance improvement by setting the blur
value to 0.0
for CGContextSetShadow
, just like I experienced with the attributed text rendition above.
Bottom line, I don't think you should fear the computational overhead of bezier-based shadows as long as you use a blur radius of 0.0
. I wouldn't be surprised if writing the text twice yourself, once for the shadow and again for the foreground color, might even be a bit more efficient, but I'm not sure if the difference will be observable. But I don't know of any API call that will do that for you (other than CGContextSetShadow
with blur
of 0.0
).