NSAttributedString superscript styling
Asked Answered
H

4

40

I want to superscript all the instances of ® character in a block of text (legal disclaimer, naturally ;)) and the default way NSAttributedString is not very good.

If I just let the character be and only use unmodified NSString, it is rendered the same size as a capital letter and is placed approximately at the baseline. If I add the superscript attribute to NSAttributedString as follows:

[attrStr setAttributes:@{(NSString *)kCTSuperscriptAttributeName : @1} range:NSMakeRange(locationOfReg, 1)];

The character is lifted off the baseline, its size is unchanged, but the line spacing is now affected because the raised character would otherwise intrude on the line above.

To illustrate:

variants of (R)

I created this image in Photoshop where the desired position was achieved by reducing the size of the character and shifting the baseline. I know how to change the font size in iOS, but changing the baseline seems trickier. Any suggestions on how to achieve this?

Edit: I suppose I could use the superscript attribute as a way to shift the baseline up. Now it would be great to figure out a way to get the current font size and subsequently reduce it to allow the same method to be used on blocks of text of different size.

Humiliation answered 28/1, 2014 at 20:21 Comment(0)
E
74

The following code seems to do the trick:

UIFont *fnt = [UIFont fontWithName:@"Helvetica" size:20.0];

NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:@"GGG®GGG"
                                                                                     attributes:@{NSFontAttributeName: [fnt fontWithSize:20]}];
[attributedString setAttributes:@{NSFontAttributeName : [fnt fontWithSize:10]
                                  , NSBaselineOffsetAttributeName : @10} range:NSMakeRange(3, 1)];

enter image description here

Elsewhere answered 6/2, 2014 at 12:38 Comment(5)
Can't make it work in iOS 6. Can you provide its replacement for iOS 6?Kristofor
Just tested under iOS 7 and added declaration for fnt that doesn't crash.Brazee
@AlexZavatone thanks! Sorry, had to remove the comment, as it's not really relevant ;)Elsewhere
AHH, DOH! That's what I get for copying and pasting!Brazee
Note: On iOS 13 there seems to be an issue if you set the maximum and minimum line height to the same value. I thought it was because of this baseline offset, but it wasn't: https://mcmap.net/q/408114/-how-to-fix-uilabel-text-spacingKaminski
H
6

Swift version:

let fnt = UIFont(name:"Helvetica", size:20.0)
let attributedString = NSMutableAttributedString(string:"GGG®GGG", attributes:[NSFontAttributeName : fnt!])
attributedString.setAttributes([NSFontAttributeName : fnt!.fontWithSize(10), NSBaselineOffsetAttributeName: 10], range: NSRange(location: 3, length: 1))
Howlyn answered 18/11, 2016 at 7:54 Comment(0)
I
5

Swift 5

    let fnt = UIFont(name:"Helvetica", size:20.0)
    let attributedString = NSMutableAttributedString(string:"2.099", attributes:[NSAttributedString.Key.font : fnt!])
    attributedString.setAttributes([NSAttributedString.Key.font : fnt!.withSize(10), NSAttributedString.Key.baselineOffset: 10], range: NSRange(location: 4, length: 1))
Intercollegiate answered 11/3, 2020 at 8:5 Comment(0)
R
2

Swift 4.2

In my example I want to subscript one instance of infinity symbol so my label's title will look like this: enter image description here

let font = UIFont(name: "Helvetica", size: 14.0)

let attributedString = NSMutableAttributedString(string: "Solids(ΔE∞)•G7®", attributes: [NSAttributedStringKey.font : font!])

attributedString.setAttributes([NSAttributedStringKey.baselineOffset: -5], range: NSRange(location: 9, length: 1))

solidsLbl.attributedText = attributedString
Raimundo answered 3/8, 2018 at 11:36 Comment(1)
Upvoted for the newer Swift names (NSAttributedStringKey.*), but you forgot to change the offset of ® to match your illustration and the question requirement.Ploce

© 2022 - 2024 — McMap. All rights reserved.