How to top-align text of different sizes within a UILabel? An example is top-aligning smaller-sized cent amount with larger-sized dollar amount in price banners.
I was able to achieve your desired result using a single label.
Using a little math you can offset the baseline of the smaller text to achieve your desired result.
Objective-C
- (NSMutableAttributedString *)styleSalePriceLabel:(NSString *)salePrice withFont:(UIFont *)font
{
if ([salePrice rangeOfString:@"."].location == NSNotFound) {
return [[NSMutableAttributedString alloc] initWithString:salePrice];
} else {
NSRange range = [salePrice rangeOfString:@"."];
range.length = (salePrice.length - range.location);
NSMutableAttributedString *stylizedPriceLabel = [[NSMutableAttributedString alloc] initWithString:salePrice];
UIFont *smallFont = [UIFont fontWithName:font.fontName size:(font.pointSize / 2)];
NSNumber *offsetAmount = @(font.capHeight - smallFont.capHeight);
[stylizedPriceLabel addAttribute:NSFontAttributeName value:smallFont range:range];
[stylizedPriceLabel addAttribute:NSBaselineOffsetAttributeName value:offsetAmount range:range];
return stylizedPriceLabel;
}
}
Swift
extension Range where Bound == String.Index {
func asNSRange() -> NSRange {
let location = self.lowerBound.encodedOffset
let length = self.lowerBound.encodedOffset - self.upperBound.encodedOffset
return NSRange(location: location, length: length)
}
}
extension String {
func asStylizedPrice(using font: UIFont) -> NSMutableAttributedString {
let stylizedPrice = NSMutableAttributedString(string: self, attributes: [.font: font])
guard var changeRange = self.range(of: ".")?.asNSRange() else {
return stylizedPrice
}
changeRange.length = self.count - changeRange.location
// forgive the force unwrapping
let changeFont = UIFont(name: font.fontName, size: (font.pointSize / 2))!
let offset = font.capHeight - changeFont.capHeight
stylizedPrice.addAttribute(.font, value: changeFont, range: changeRange)
stylizedPrice.addAttribute(.baselineOffset, value: offset, range: changeRange)
return stylizedPrice
}
}
This yields the following: