Center two fonts with different different sizes vertically in an NSAttributedString

IosNsattributedstring

Ios Problem Overview


I use NSAttributedString to generate a string with two different sizes. By default, its bottom alignment looks like this:

baseline aligned sizes

But I want to center it vertically, like this: vertically centered sizes

To be clear, this is a single attributed string, not two or more. This is a simplified example to describe my question, what I'd actually like to do is more complex.

Ios Solutions


Solution 1 - Ios

I'd say the easiest thing to do is just manipulate the NSBaselineOffsetAttributeName attribute for the text in question:

> NSBaselineOffsetAttributeName > >The value of this attribute is an NSNumber object containing a floating point value indicating the character’s offset from the baseline, in points. The default value is 0.

To center, you'd take the difference between height of the large text and the height of the smaller text and halve it, then use that as the baseline adjustment.

Solution 2 - Ios

Here is a working example to vertically align smaller text using NSBaselineOffsetAttributeName.

NSString *bigString   = @"BIG";
NSString *smallString = @"Small String";
NSString *fullString = [NSString stringWithFormat:@"%@ %@", bigString, smallString];

NSMutableAttributedString *string = [[NSMutableAttributedString alloc] initWithString:fullString];

NSRange bigStringRange = NSMakeRange(0, bigString.length);
NSRange smallStringRange = NSMakeRange(bigStringRange.length, smallString.length);

[string beginEditing];


//Set big string font and size
[string addAttribute:NSFontAttributeName
               value:[UIFont systemFontOfSize:28.0]
               range:bigStringRange];

//set small string font and size
[string addAttribute:NSFontAttributeName
               value:[UIFont systemFontOfSize:18.0]
               range:smallStringRange];

//Set small string baseline offset
[string addAttribute:NSBaselineOffsetAttributeName
               value:[NSNumber numberWithFloat:3.0]  //adjust this number till text appears to be centered
               range:smallStringRange];

[string endEditing];

Solution 3 - Ios

YasT's answer in Swift:

Swift 4

let bigString = "BIG"
let smallString = "Small String"
let fullString = "\(bigString) \(smallString)"
let string = NSMutableAttributedString(string: fullString)

let bigStringRange = NSRange(location: 0, length: bigString.utf16.count)
let smallStringRange = NSRange(location: bigStringRange.length + 1, length: smallString.utf16.count)

let bigStringFontSize: CGFloat = 28
let smallStringFontSize: CGFloat = 18

string.beginEditing()

string.addAttribute(.font, value: UIFont.systemFont(ofSize: bigStringFontSize), range: bigStringRange)
string.addAttribute(.font, value: UIFont.systemFont(ofSize: smallStringFontSize), range: smallStringRange)
string.addAttribute(.baselineOffset, value: (bigStringFontSize - smallStringFontSize) / 2, range: smallStringRange)

string.endEditing()

Swift 3

let bigString = "BIG"
let smallString = "Small String"
let fullString = "\(bigString) \(smallString)"
let string = NSMutableAttributedString(string: fullString)

let bigStringRange = NSRange(location: 0, length: bigString.utf16.count)
let smallStringRange = NSRange(location: bigStringRange.length + 1, length: smallString.utf16.count)

let bigStringFontSize: CGFloat = 28
let smallStringFontSize: CGFloat = 18

string.beginEditing()

string.addAttribute(NSFontAttributeName, value: UIFont.systemFont(ofSize: bigStringFontSize), range: bigStringRange)
string.addAttribute(NSFontAttributeName, value: UIFont.systemFont(ofSize: smallStringFontSize), range: smallStringRange)
string.addAttribute(NSBaselineOffsetAttributeName, value: (bigStringFontSize - smallStringFontSize) / 2, range: smallStringRange)

string.endEditing()

Solution 4 - Ios

Better solution is calculating NSBaselineOffsetAttributeName from fonts typography (short article https://www.raizlabs.com/dev/2015/08/advanced-ios-typography/)

Set attribute for second part of attributed string.

secondPartAttributes[NSBaselineOffsetAttributeName] = @((firstFont.xHeight - secondFont.xHeight)/2);

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser2608857View Question on Stackoverflow
Solution 1 - IosBen LachmanView Answer on Stackoverflow
Solution 2 - IosYas TabasamView Answer on Stackoverflow
Solution 3 - IosTamás SengelView Answer on Stackoverflow
Solution 4 - IosRamanView Answer on Stackoverflow