Scaling NSAttributedString with Size Classes in iOS - ios

I'm using NSAttributedString to make a section of a UILabel bold, and I've been looking at how I might scale the font across different size classes.
The only way I can currently see to do this is to use the existing font size of the label when adding the attribute:
CGFloat fontSize = self.label.font.pointSize;
NSMutableAttributedString * string = [[NSMutableAttributedString alloc] initWithString:#"Abc Abc"];
[string addAttribute:NSFontAttributeName
value:[UIFont boldSystemFontOfSize:fontSize]
range:NSMakeRange(0,3)];
self.label.attributedText = string;
To clarify: label is a UILabel with a regular system font, and the attributed string is used to make the first 3 letters bold.
This works reasonably well, but couples the creation of the attributed string with the label. Is there a way to scale the attributed string without knowing the font size up front?

After discussion with #Larcerax, I found that I could use the Autoshrink property on my UILabel in Interface Builder to ensure the font scales down appropriately, which gives the (somewhat dirty) solution of using an obscenely large maximum font size which can be scaled down:
NSMutableAttributedString * string = [[NSMutableAttributedString alloc] initWithString:#"Abc Abc"];
[string addAttribute:NSFontAttributeName
value:[UIFont boldSystemFontOfSize:200.0]
range:NSMakeRange(0,3)];
self.label.attributedText = string;
This does require deciding upon a maximum size ahead of time, though.

Related

IOS Objective C UILabel font size is keeping its storyboard setting

I am using objectiveC for an old project and I am setting the label font size programmatically like this :
UIFont *font = [self fontToFitHeight:NSLocalizedString(#"#61_NEW_FINAL", nil) font:self.rulesLabel.font size:self.rulesLabel.frame.size.height];
[self.rulesLabel setFont:font];
NSLog(#"after call : fontszie is : %lf",self.rulesLabel.font.pointSize);
I can include the helper function if needed, but it returns me what I want, which is a font with fontsize around 5, which i see printed.
But when running that my font size is definitely not 5, but instead whatever value I have in the Storyboard settings (in my case 16). Above code is called inside viewDidLoad.
What am I missing?
NSAttributedString can include one or more fonts, perhaps this is your issue. If you have set the text of the label to be an attributed string that contains a font or a color, changing the base font or color of the label will not make a difference. In order for it to work as expected, you can either remove any font formatting of your attributed string (that I assume that you set through IB) or recreate the string in code and add the proper font to it, like so:
NSString *text = NSLocalizedString(#"#61_NEW_FINAL", #"Don't leave this out");
UIFont *font = [self fontToFitHeight:text font:self.rulesLabel.font size:self.rulesLabel.frame.size.height];
NSMutableAttributedString *labelAttributes = [[NSMutableAttributedString alloc] initWithString:text];
[labelAttributes addAttribute:NSFontAttributeName
value:font
range:NSMakeRange(0, labelAttributes.length)];
At this point, changing the font of the label will make absolutely no difference to its apperance, since the entire text has a predefined font already.

How to increase font size of whole content in NSMutableAttributedString

I want to increase font size of text that comes from server and text is in html format.I used NSAttributedString for showing text.
NSRange rangeOfTitle = NSMakeRange(0,[catDescLabel length]);
NSMutableAttributedString *string1 =
[[NSMutableAttributedString alloc] initWithString:catDescLabel];
[string1 addAttribute:NSFontAttributeName
value:[UIFont systemFontOfSize:20.0]
range:rangeOfTitle];
I am attaching screenshot that how it look and i am also attaching screenshot how it look in Android.I want to increase font size of whole content. how can i do this ?
Could anyone give me any Idea or help. Much appreciated
Android Screenshot
iOS Screenshot
Thanks ,
addAttribute ... but it seems it is not available for NSAttributedString
But it is available for NSMutableAttributedString.
That's how it is with all Cocoa immutable/mutable class pairs. The immutable member of the pair is, uh, immutable — that means you can't change anything about it. If you want to change something about it, convert it to the mutable member of the pair.
NSMutableAttributedString *attributedString2 =
[[NSMutableAttributedString alloc] initWithAttributedString: attributedString1];
You would do something like this…
NSMutableAttributedString *string1 =
[[NSMutableAttributedString alloc] initWithString:#"Your string"];
[string1 addAttribute:NSFontAttributeName
value:[UIFont systemFontOfSize:20.0]
range:NSMakeRange(5, 6)];
Update :
[self.label setAttributedTitle:string1];
This will set the last two words in 20-point text; the rest of the string will use the default value (which I believe is 12 points). The thing that might be confusing about setting the text size is that you have to set the typeface and the size at the same time—each UIFont object encapsulates both of those properties.
And reference link for you
https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/AttributedStrings/Tasks/CreatingAttributedStrings.html

Format text in UITextView

I am making an "About Page" for my application, and I have to paste pretty huge amount of text on that page (text will not be editable).
I am using a UITextView for this purpose. However, I need some words to be in bold (like headings). But I am not able to achieve it. The UITextView removes all my formatting.
I have no code to show here because I am pasting all my text in the IB only.
Is there any workaround?? For example.. I want the heading in bold..
"About ABC Corporation
gkskgsagdfgfskgfjkgfgljdgsfjgdsjfgdjlsgflgdslgfljdsgfljgdsjlgfljdsgfljdgslfgls.
jdfjkhdsjlfhdlsfhkldshfkldshflkdhlkfhdklsfhlksdhflkdshflkhdsflkhsdklfhlksdhflkshf
fjhdshfkldshfkldhsfklhdsklfhlkdshfklhdsklfhdklsfhkdshfklhdsklfhklsdfhkldshfkhdsklf
fhjdgfkdgsjkfgjkdsgfjkdsgjfgjdkgfjgsjdfgjkdsgfjkgsdjkfgjsdgfjgsdjkfgjksdgfjkgskjfgs"
First keep text property of textView as 'Attributed', after that just select the text and change it's style and font as you want.
P.S. - All you have to do this in Attribute inspector panel of IB.
EDIT:
For more, visit this link .
Also, this is very good mainly when the textField have a text that will not change, e.g. - like About info. And when this text is inserted in IB directly instead of assigning text programmaticaly.
You can use NSAttributedString, Set Text Font, Foreground And Background Colors, StrikeThrough And Shadow etc..
Attributed strings make an association between characters and their attributes. Like NSString objects, there are two variations, NSAttributedString and NSMutableAttributedString. Although previous versions of iOS supported attributed strings, it wasn’t until iOS 6 that controls such as buttons, labels, textfields and textviews defined a property to manage attributes. Attributes are applied to a range of characters, so you can for example, set a strikethrough attribute for just a portion of a string. It’s also important to note that the default font for attributed string objects is Helvetica 12-point. Keep this in mind if you set the font attribute for a range other than the complete string. The following attributes can be set with attributed strings:
NSString *const NSFontAttributeName;
NSString *const NSParagraphStyleAttributeName;
NSString *const NSForegroundColorAttributeName;
NSString *const NSBackgroundColorAttributeName;
NSString *const NSLigatureAttributeName;
NSString *const NSKernAttributeName;
NSString *const NSStrikethroughStyleAttributeName;
NSString *const NSUnderlineStyleAttributeName;
NSString *const NSStrokeColorAttributeName;
NSString *const NSStrokeWidthAttributeName;
NSString *const NSShadowAttributeName;
NSString *const NSVerticalGlyphFormAttributeName;
// Create attributed string
NSString *str = #"example for underline \nexample for font \nexample for bold \nexample for italics";
NSMutableAttributedString *attributedString =
[[NSMutableAttributedString alloc] initWithString:str];
// Add attribute NSUnderlineStyleAttributeName
[attributedString addAttribute:NSUnderlineStyleAttributeName
value:[NSNumber numberWithInt:NSUnderlineStyleSingle]
range:NSMakeRange(12, 9)];
[attributedString addAttribute:NSUnderlineStyleAttributeName
value:[NSNumber numberWithInt:NSUnderlineStyleSingle]
range:NSMakeRange(12, 9)];
// Set background color for entire range
[attributedString addAttribute:NSBackgroundColorAttributeName
value:[UIColor yellowColor]
range:NSMakeRange(0, [attributedString length])];
// Create NSMutableParagraphStyle object
NSMutableParagraphStyle *paragraph = [[NSMutableParagraphStyle alloc] init];
paragraph.alignment = NSTextAlignmentCenter;
// Add attribute NSParagraphStyleAttributeName
[attributedString addAttribute:NSParagraphStyleAttributeName
value:paragraph
range:NSMakeRange(0, [attributedString length])];
// Set font, notice the range is for the whole string
UIFont *font = [UIFont fontWithName:#"Helvetica" size:18];
[attributedString addAttribute:NSFontAttributeName
value:font
range:NSMakeRange(35, 4)];
// Set font, notice the range is for the whole string
UIFont *fontBold = [UIFont fontWithName:#"Helvetica-Bold" size:18];
[attributedString addAttribute:NSFontAttributeName
value:fontBold
range:NSMakeRange(53, 4)];
// Set font, notice the range is for the whole string
UIFont *fontItalics = [UIFont fontWithName:#"Helvetica-Oblique" size:18];
[attributedString addAttribute:NSFontAttributeName
value:fontItalics
range:NSMakeRange(71, 7)];
// Set label text to attributed string
[self.mytextView setAttributedText:attributedString];
Check out attributedText property of UITextView
https://developer.apple.com/library/ios/documentation/uikit/reference/uitextview_class/Reference/UITextView.html#//apple_ref/occ/instp/UITextView/attributedText
And this how you can make part of your string bold
Any way to bold part of a NSString?
You can use NSMutableAttributedString to support multi attribute property to your string.Note:- NSMutableAttributedString is available in iOS 6.0+. Edit:- Check this:- How to create a UILabel or UITextView with bold and normal text in it?
iOS SDK has included text kit in it.
iOS 7 offers the ability to enhance the legibility of text by increasing font weight, as well as an option to set the preferred font size for apps that support dynamic text. Users will expect apps written for iOS7 to honor these settings, so ignore them at your own risk!
In order to make use of dynamic type you need to specify fonts using styles rather than explicitly stating the font name and size. With iOS 7 a new method has been added to UIFont, preferredFontForTextStyle that creates a font for the given style using the user’s font preferences.
Here is a great tutorial in great website Ray wenderlich text kit tutorial
If you have time, watch WWDC 2013 video session 201
UITextView is a plain text and you can't apply different styles(font,color) for different words.
I suggest you to use UIWebView. It is html, so it can be styled.

Letter spacing in iOS

I have the following code:
[[cancelButton titleLabel] setFont:[UIFont fontWithName:#"ProximaNova-Regular" size:15]];
How would I set the letter-spacing as well?
You can't change the letter spacing in the abstract, which means that you can't change it at all under iOS 5 and below.
As of iOS 6, you can push an attributed string rather than a vanilla one to a UILabel. The process for pushing an attributed string works slightly differently from the process for pushing an ordinary one — the font, text colour and a bunch of other properties are all set on the string rather than on the label. The reason is that attributed strings allow different attributes to be set for different regions of the string. So you can set a string that combines multiple fonts, text colours, etc.
One of the supported Core Text attributes is kCTKernAttributeName, which as of iOS 6 is easier to take advantage of via the UIKit addition NSKernAttributeName. You can use kerning to adjust the horizontal spacing of glyphs.
Under iOS 5 and earlier you used to have to do a lot of mental jumping back and forth between Core Foundation C-style objects and Objective-C UIKit objects. As of 6 that's no longer necessary. But be wary if you search the 'net that things got a lot easier under 6 — if you see lots of __bridge casts and manual CFReleases then you're probably looking at older code.
Anyway, supposing you currently have something like:
UILabel *label = [cancelButton titleLabel];
UIFont *font = <whatever>;
UIColor *textColour = <whatever>;
NSString *string = <whatever>;
label.text = string;
label.font = font;
label.textColor = textColour;
You'd instead do something more like:
NSAttributedString *attributedString =
[[NSAttributedString alloc]
initWithString:string
attributes:
#{
NSFontAttributeName : font,
NSForegroundColorAttributeName : textColour
}];
label.attributedText = attributedString;
In your case, also to adjust the overall kerning you'd add:
NSAttributedString *attributedString =
[[NSAttributedString alloc]
initWithString:string
attributes:
#{
NSFontAttributeName : font,
NSForegroundColorAttributeName : textColour,
NSKernAttributeName : #(-1.3f)
}];
label.attributedText = attributedString;
Or whatever kerning value you want to apply. See the various constants at the bottom of the NSAttributedString UIKit Additions Reference for the various other attributes you can apply and which version of iOS they first became available on.
Much later addendum: while still being one of the least Swifty people you'll meet, I think this is the equivalent in Swift:
button.titleLabel?.attributedText =
NSAttributedString(
string: string,
attributes:
[
NSFontAttributeName: font,
NSForegroundColorAttributeName: textColour,
NSKernAttributeName: -1.3
])
NSAttributedString *cancelButtonAttributedString = [[NSAttributedString alloc]
initWithString:#"Hello"
attributes:
#{
NSKernAttributeName: #(1.5)
}];
[cancelButton setAttributedTitle:cancelButtonAttributedString forState:UIControlStateNormal];
This is only simple answer for above question
One of the supported Core Text attributes is kCTKernAttributeName, which as of iOS 6 is easier to take advantage of via the UIKit addition NSKernAttributeName. You can use kerning to adjust the horizontal spacing of glyphs.
Kerning is the adjustment of space between two unique letters. Kerning varies between different character pairs. For example, a combination like 'AVA' would have a different kerning between characters than something like 'VVV'
By using NSKernAttributeName, you're actually overriding that custom space adjustment that is built into the font file, setting all the various character pair kern values to the same number, thus breaking the optimal kerning. When applied to an entire string of text, small amounts of kerning the broken spacing is more noticeable. However, high kerning values could push the letter far enough apart to the point that the poor spacing will not be as noticeable.
What you're looking for is Tracking (aka letter spacing), which is the spacing between all the letters in a given block of text. Unfortunately, iOS does not seem to let you control that attribute.

UILabel attributedText with multiple line break modes

I have a requirement of showing a UILabel with text that has two different styles (different colours, parts of the text bolded). This is solved easily enough by using the attributedText-property.
My problem is that the text may or may not be longer than what I can fit in my label. When using plain text everything works the way I want it to. The text is word wrapped to fit the number of lines in the label and the tail is truncated if/when the text is longer than can be shown in the label.
When I switch to using attributedText I am only able to choose between tail truncation and word wrapping. If I want the tail truncated the label only renders a single line with the truncated tail (even though it could fit 10 lines). If I choose word wrapping then the tail is not truncated but the lines that cannot fit in the label are simply not shown.
My content string does not contain any line breaks, it is simply one long string.
I missed truncation when I set linespacing, but all I had to to was add linebreakmode to paragraphstyle
NSMutableParagraphStyle *paragrahStyle = [[NSMutableParagraphStyle alloc] init];
[paragrahStyle setLineSpacing:1.5];
[paragrahStyle setLineBreakMode:NSLineBreakByTruncatingTail];
NSMutableAttributedString *attributedText = [[NSMutableAttributedString alloc] initWithString:#"Long string that truncates"];
[attributedText addAttribute:NSParagraphStyleAttributeName value:paragrahStyle range:NSMakeRange(0, [attributedText length])];
self.label.attributedText = attributedText;
They only way I've been able to get this to work is to not set a paragraph style.
try this:
[_text drawWithRect:_textRect
options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingTruncatesLastVisibleLine
attributes:attributes
context:nil];
You can set up an NSParagraphStyle with any lineBreakMode you please, and apply it to the string using NSParagraphStyleAttributeName. I don't know if all of the values of NSLineBreakMode are supported, but I have no reason to believe they aren't.

Resources