Shadow effect for NSString - iphone

I want to apply shadow effect to text of type NSString.
Though I understand how to apply shadow effect to UILabel and other view elements,
I can't figure out a way of adding shadow effect to text.
I am currently drawing text as follows:
NSString *text = #"Hello";
[text drawAtPoint:point width withFont:font minFontSize:22.0f actualFontSize:&actualFontSize lineBreakMode:UILineBreakModeTailTruncation baselineAdjustment:UIBaselineAdjustmentAlignBaselines];
I would really appreciate any help. Thanks!

Try CGContextSetShadow() for adding shadow to text
- (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]];
}

Related

WatchKit: How can I implement a text shadow?

In my Apple Watch app, I'm trying to place text over the top of an image. I've got a group with a background image and label positioned correctly. But depending on the image, my white text can sometimes be unreadable. Dark text would have the same problem or be even worse.
Is there a way to have black text just under my white text and slightly offset?
Unfortunately, the current version of WatchKit doesn't provide a way to "stack" or layer WKInterfaceLabel controls. So, the idea of including black text under the white text using a second label won't work.
You might consider rendering your drop-shadowed text as a UIImage in your Watch extension and using the image with a WKInterfaceImage control. Something like:
- (UIImage *)imageWithText:(NSString *)text shadowBlurRadius:(CGFloat)shadowBlurRadius {
NSShadow *shadow = [[NSShadow alloc] init];
shadow.shadowOffset = CGSizeZero;
shadow.shadowBlurRadius = shadowBlurRadius;
shadow.shadowColor = [UIColor blackColor];
NSDictionary *attributes = #{ NSForegroundColorAttributeName : [UIColor whiteColor],
NSFontAttributeName : [UIFont boldSystemFontOfSize:36.0f],
NSShadowAttributeName : shadow };
CGSize size = [text sizeWithAttributes:attributes];
UIGraphicsBeginImageContextWithOptions(CGSizeMake(size.width + (2.0f * shadowBlurRadius),
size.height + (2.0f * shadowBlurRadius)),
NO,
2.0f);
[text drawAtPoint:CGPointMake(shadowBlurRadius, shadowBlurRadius)
withAttributes:attributes];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}

iPhone: Create image from NSString with word wrap

I am using following function for converting an NSString to an image.
-(UIImage *)imageFromText:(NSString *)text FontName:(UIFont *)font
{
// set the font type and size
//UIFont *font = [UIFont systemFontOfSize:20.0];
CGSize size = [text sizeWithFont:font];
UIGraphicsBeginImageContext(size);
[text drawAtPoint:CGPointMake(0.0, 0.0) withFont:font];
// transfer image
CGContextSetShouldAntialias(UIGraphicsGetCurrentContext(), YES);
CGContextSetAllowsAntialiasing(UIGraphicsGetCurrentContext(), YES);
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
It works well. The problem is that when the string contains long text, then it creates an image for which the width is too much. I want to apply a word wrap functionality if the text beyond the range.
So how can I create a image with word wrap of NSString?
You need to call drawInRect:withAttributes: method on NSString.

NSString drawinrect not fills whole rect

I'm having a problem with NSString drawInRect method.
I have a very large text to be painted over a 768x1024 size Rect and I obtain this:
As you can see the only text line that reaches the whole screen is the last one, I don't know why other lines don't.
This is my code:
//The drawing rectangle
CGRect textRect = CGRectMake(1, 4, 768, 1024);
[[UIColor blackColor] set];
CGContextSetTextDrawingMode(context, kCGTextFillStroke);
//texto_completo is a very large text String
[texto_completo drawInRect:textRect withFont:font lineBreakMode:UILineBreakModeCharacterWrap alignment:UITextAlignmentLeft];
CGImageRef cgImage = CGBitmapContextCreateImage(context);
UIImage *img_con_texto = [[UIImage alloc] initWithCGImage:cgImage];
UIGraphicsPopContext();
CGContextRelease(context);
CGImageRelease(cgImage);
Could you help me understand this behaviour?
It looks like the APple algorithm is over aggressive.
The best solution is to set the alignment to UITextAlignmentCenter, that is the only way top get the characters flush right. In my test the lime breaks were the same as with alignment UITextAlignmentLeft.

Why is the newline character not working when I draw a string within -drawRect:?

the Newline character is not working in draw rect of UIView? can anyone help?
- (void)drawRect:(CGRect)rect
{
CGContextRef context = UIGraphicsGetCurrentContext();
UIFont * f = [UIFont systemFontOfSize:20];
[[UIColor darkGrayColor] set];
CGRect b = [self bounds];
NSString * text = #"hi \nr u";
CGSize sz = CGSizeMake(150,200);
CGContextScaleCTM(context, b.size.width/sz.width, b.size.height/sz.height);
[text drawAtPoint:CGPointMake(0,0) withFont:f];
}
Consider using drawInRect:withFont: instead of drawAtPoint:withFont:, as the latter only supports a single line of text.

How to draw bordered letter?

I am searching about drawing bordered text on UIView.
Implemented following method :
- (void)drawRect:(CGRect)rect {
//TODO draw bordered text here.
}
How to draw it ?
I mean each letter is bordered of whole text.
Thanks in advance.
To display bordered text (if I understand correctly what you want) you should set text drawing mode to kCGTextFillStroke (and set appropriate values for text drawing parameters, such as stroke and fill colors etc)
// Choose appropriate text font
CGContextSelectFont(context, [[UIFont boldSystemFontOfSize:24].fontName UTF8String], (int)fontSize, kCGEncodingMacRoman);
// Set text drawing mode
CGContextSetTextDrawingMode(context, kCGTextFillStroke);
// Set appropriate color/line width values
// Here we're set to draw white letters with black border
CGContextSetRGBStrokeColor(context, 0, 0, 0, 1);
CGContextSetRGBFillColor(context, 1, 1, 1, 1);
CGContextSetLineWidth(context, 1);
// Set this transformations or text will be displayed upside-down
CGAffineTransform xform = CGAffineTransformMake(1.0, 0.0, 0.0, -1.0, 0.0, 0.0);
CGContextSetTextMatrix(context, xform);
// Display text
CGContextShowTextAtPoint(...);
Edit: As Quartz does not work well with unicode, to draw unicode strings you'll need to use other APIs. I managed to draw "bordered" unicode string using NSAttributedString and OHAttributedLabel (thanks to this answer for that custom control). Sample code to get required string in some view controller:
- (void)viewDidLoad
{
[super viewDidLoad];
NSMutableAttributedString *s = [[NSMutableAttributedString alloc] initWithString:#"您好世界"];
[s addAttributes:[NSDictionary dictionaryWithObject:[NSNumber numberWithFloat:-3.0f] forKey:(NSString*)kCTStrokeWidthAttributeName]
range:NSMakeRange(0, [s length])];
[s addAttributes:[NSDictionary dictionaryWithObject:(id)[UIColor greenColor].CGColor forKey:(NSString*)kCTStrokeColorAttributeName]
range:NSMakeRange(0, [s length])];
[s addAttributes:[NSDictionary dictionaryWithObject:(id)[UIColor redColor].CGColor forKey:(NSString*)kCTForegroundColorAttributeName]
range:NSMakeRange(0, [s length])];
[s setFont:[UIFont boldSystemFontOfSize:28.0f]];
[s setTextColor:[UIColor redColor]];
OHAttributedLabel *l = [[OHAttributedLabel alloc] initWithFrame:CGRectMake(40.0f, 40.0f, 200.0f, 80.0f)];
l.centerVertically = YES;
[l setAttributedText: s];
[self.view addSubview: l];
[l release];
}
Note that you'll need to link with CoreText.framework to make that work, and code uses some convenience methods provided in OHAttributedLabel implementation
I tried this way:
draw with NSString drawAtPoint:withFont: or drawInRect:withFont:
set line joint and lin cap to round.
draw your text with the border color using drawing mode kCGTextStroke, be sure to set the line width a little wider,
then draw your text with its inner color using drawing mode kCGTextFill.
may be you need a little adjustment in the position to make it perfect.