How to Both Stroke and Fill with Nsattributedstring W/ Uilabel

How can I both stroke and fill with NSAttributedString w/ UILabel

Yes, the key is to apply a Negative value to the NSStrokeWidthAttributeName
If this value is positive you will only see the stroke and not the fill.

Objective-C:

self.label.attributedText=[[NSAttributedString alloc] 
initWithString:@"string to both stroke and fill"
attributes:@{
NSStrokeWidthAttributeName: @-3.0,
NSStrokeColorAttributeName:[UIColor yellowColor],
NSForegroundColorAttributeName:[UIColor redColor]
}
];

Thanks to @cacau below: See also Technical Q&A QA1531

Swift 4 version:

let attributes: [NSAttributedStringKey : Any] = [.strokeWidth: -3.0,
.strokeColor: UIColor.yellow,
.foregroundColor: UIColor.red]

label.attributedText = NSAttributedString(string: text, attributes: attributes)

Swift 5.1 version:

let attributes: [NSAttributedString.Key : Any] = [.strokeWidth: -3.0,
.strokeColor: UIColor.yellow,
.foregroundColor: UIColor.red]

label.attributedText = NSAttributedString(string: text, attributes: attributes)

How do you stroke the _outside_ of an NSAttributedString?

While there may be other ways, one way to accomplish this is to first draw the string with only a stroke, then draw the string with only a fill, directly overtop of what was previously drawn. (Adobe InDesign actually has this built-in, where it will appear to only apply the stroke to the outside of letter, which helps with readability).

This is just an example view that shows how to accomplish this (inspired by http://developer.apple.com/library/mac/#qa/qa2008/qa1531.html):

First set up the attributes:

@implementation MDInDesignTextView

static NSMutableDictionary *regularAttributes = nil;
static NSMutableDictionary *indesignBackgroundAttributes = nil;
static NSMutableDictionary *indesignForegroundAttributes = nil;

- (void)drawRect:(NSRect)frame {
NSString *string = @"Got stroke?";
if (regularAttributes == nil) {
regularAttributes = [[NSMutableDictionary
dictionaryWithObjectsAndKeys:
[NSFont systemFontOfSize:64.0],NSFontAttributeName,
[NSColor whiteColor],NSForegroundColorAttributeName,
[NSNumber numberWithFloat:-5.0],NSStrokeWidthAttributeName,
[NSColor blackColor],NSStrokeColorAttributeName, nil] retain];
}

if (indesignBackgroundAttributes == nil) {
indesignBackgroundAttributes = [[NSMutableDictionary
dictionaryWithObjectsAndKeys:
[NSFont systemFontOfSize:64.0],NSFontAttributeName,
[NSNumber numberWithFloat:-5.0],NSStrokeWidthAttributeName,
[NSColor blackColor],NSStrokeColorAttributeName, nil] retain];
}

if (indesignForegroundAttributes == nil) {
indesignForegroundAttributes = [[NSMutableDictionary
dictionaryWithObjectsAndKeys:
[NSFont systemFontOfSize:64.0],NSFontAttributeName,
[NSColor whiteColor],NSForegroundColorAttributeName, nil] retain];
}

[[NSColor grayColor] set];
[NSBezierPath fillRect:frame];

// draw top string
[string drawAtPoint:
NSMakePoint(frame.origin.x + 200.0, frame.origin.y + 200.0)
withAttributes:regularAttributes];

// draw bottom string in two passes
[string drawAtPoint:
NSMakePoint(frame.origin.x + 200.0, frame.origin.y + 140.0)
withAttributes:indesignBackgroundAttributes];
[string drawAtPoint:
NSMakePoint(frame.origin.x + 200.0, frame.origin.y + 140.0)
withAttributes:indesignForegroundAttributes];
}

@end

This produces the following output:

alt text

alt text

Now, it's not perfect, since the glyphs will sometimes fall on fractional boundaries, but, it certainly looks better than the default.

If performance is an issue, you could always look into dropping down to a slightly lower level, such as CoreGraphics or CoreText.

How do I make UILabel display outlined text?

I was able to do it by overriding drawTextInRect:

- (void)drawTextInRect:(CGRect)rect {

CGSize shadowOffset = self.shadowOffset;
UIColor *textColor = self.textColor;

CGContextRef c = UIGraphicsGetCurrentContext();
CGContextSetLineWidth(c, 1);
CGContextSetLineJoin(c, kCGLineJoinRound);

CGContextSetTextDrawingMode(c, kCGTextStroke);
self.textColor = [UIColor whiteColor];
[super drawTextInRect:rect];

CGContextSetTextDrawingMode(c, kCGTextFill);
self.textColor = textColor;
self.shadowOffset = CGSizeMake(0, 0);
[super drawTextInRect:rect];

self.shadowOffset = shadowOffset;

}

Swift NSAttributedStringKey not applying foreground color correctly

Use negative strokeWidth if you'll set foregroundColor as well. Otherwise, only the stroke is seen.

let attributes = [
NSAttributedStringKey.strokeColor.rawValue: UIColor.black,
NSAttributedStringKey.backgroundColor.rawValue: UIColor.red,
NSAttributedStringKey.foregroundColor.rawValue: UIColor.white,
NSAttributedStringKey.font.rawValue: UIFont(name: "HelveticaNeue-CondensedBlack", size: 40)!,
NSAttributedStringKey.strokeWidth.rawValue: -4.5]

Swift 5

let attributes = [
NSAttributedString.Key.strokeColor: UIColor.black,
NSAttributedString.Key.backgroundColor: UIColor.red,
NSAttributedString.Key.foregroundColor: UIColor.white,
NSAttributedString.Key.font: UIFont(name: "HelveticaNeue-CondensedBlack", size: 40)!,
NSAttributedString.Key.strokeWidth: -3.0]

Edit: See rmaddy's comment about why we need the rawValue in this case below.

How to draw border around a UILabel?

You can set label's border via its underlying CALayer property:

#import <QuartzCore/QuartzCore.h>

myLabel.layer.borderColor = [UIColor greenColor].CGColor
myLabel.layer.borderWidth = 3.0

Swift 5:

myLabel.layer.borderColor = UIColor.darkGray.cgColor
myLabel.layer.borderWidth = 3.0

make UILabel's text bold

Try

[infoLabel setFont:[UIFont fontWithName:@"Arial-BoldMT" size:16]];

It may also be worth checking if the font you're trying to use is available on device

Setting BOLD font on iOS UILabel

UPDATE:
Starting with iOS 8, messing with font names is no longer needed. Instead see newer answers that use UIFontDescriptorSymbolicTraits: here and here.


myLabel.font = [UIFont fontWithName:@"Helvetica-Bold" size:14];

If you wanna set it programmatically,you must check bold type is support or not in iOS, normally Bold or Italic will have format FontName-Bold, FontName-Italic, FontName-BoldItalic.

Now, write a bold function

-(void)boldFontForLabel:(UILabel *)label{
UIFont *currentFont = label.font;
UIFont *newFont = [UIFont fontWithName:[NSString stringWithFormat:@"%@-Bold",currentFont.fontName] size:currentFont.pointSize];
label.font = newFont;
}

Then call it

[self boldFontForLabel:yourLabel];


Related Topics



Leave a reply



Submit