Adding a drop shadow to NSString text in a drawRect: method without using UILabel
Asked Answered
M

1

22

I'd like to add a drop shadow to text drawn using the iOS supplied NSString (UIStringDrawing) category method:

- (CGSize)drawAtPoint:(CGPoint)point forWidth:(CGFloat)width 
             withFont:(UIFont *)font minFontSize:(CGFloat)minFontSize 
       actualFontSize:(CGFloat *)actualFontSize 
        lineBreakMode:(UILineBreakMode)lineBreakMode
   baselineAdjustment:(UIBaselineAdjustment)baselineAdjustment; 

Clearly, there's no drop shadow option.

Yes, one could use a UILabel here and get drop shadow properties to set, but that wouldn't be as performant, since any UIView subclass (such as UILabel) wraps a CALayer object and is going to be heavier (performance wise).

Here's the context:

I'm doing custom drawing for a UITableViewCell subclass, implementing drawRect: on the table cell view instead of creating the table cell from a Nib file of composited UIView subclasses.

Compositing a bunch of UIView subclasses would defeat the purpose of trying to keep this lean and stay within 50-60 frames per second in table view scrolling performance.

I have tried drawing the string twice at a slight offset. This may turn out acceptable once I tweak the drop shadow color on the background color of the cell that I have going, but it seems rather kludgey. Certainly there's no drop shadow blur property like one gets with UILabel.

I searched for solutions and they either recommend UILabel usage (which I've dismissed per above, since I have about a dozen distinct textual elements getting composited on to the table cell view) or CGContextSetShadow(). The latter always seems to be suggested in the context of rectangular shapes, and not necessarily for attaching a shadow to the path of text drawn directly with the NSString drawAtPoint... method mentioned above. (I did try it, but it didn't seem to work (i.e. nothing changed); I'm new to Core Graphics drawing).

Suggestions?

Member answered 8/12, 2010 at 14:10 Comment(0)
L
40

It works fine for me with CGContextSetShadow(). Example:

- (void)drawRect:(CGRect)rect 
{
    NSString *string = @"Hello World!";

    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSetShadow(context, CGSizeMake(20.0f, 20.0f), 10.0f);

    [string drawAtPoint:CGPointMake(100.0f, 100.0f) withFont:[UIFont boldSystemFontOfSize:36.0f]];
}
Lamp answered 8/12, 2010 at 14:24 Comment(1)
Excellent. Thanks Ole! Prior, I think I had too high a blur value and a offset of just (1,1) and so I couldn't see it taking effect. As I'm new to this, the next challenge I had was turning off the shadow effect for subsequent drawings (I really just need to read the Quartz 2D guide systematically). However, I did fine success in using "CGContextSaveGState(context)" before the shadow effect is set and "CGContextRestoreGState(context)" after the NSString has done it's drawing. I'm all set!Member

© 2022 - 2024 — McMap. All rights reserved.