I'm adding an icon to a UILabel
using NSTextAttachment
inside an NSMutableAttributedString
like this:
//Setting up icon
let moneyIcon = NSTextAttachment()
moneyIcon.image = UIImage(named: "MoneyIcon")
let moneyIconString = NSAttributedString(attachment: moneyIcon)
//Setting up text
let balanceString = NSMutableAttributedString(string: " 1,702,200")
balanceString.insert(moneyIconString, at: 0)
//Adding string to label
self.attributedText = balanceString
self.sizeToFit()
But for some reason the icon isn't vertically aligned
Does anybody know how can I align it?
Thank you!
EDIT: Use capHeight from this answer.
This answer, which is about vertically centering two differently sized fonts in a single NSAttributedString
, mentions using the baseline offset to calculate the center of the string.
You can use the same approach when using an image:
Subtract the font size from the image's height and divide it by 2.
Subtract the font's descender from the value (since font size isn't the same as the ascent of your font). The font that you are particularly using (Baloo-Regular) has a descender value that differs from the standard and it should be divided by 2. Other fonts (including San Fransisco) don't need that fix or require a different divisor.
This code covers most cases, if your font behaves differently, you should check out the guide for managing texts in Text Kit.
// *Setting up icon*
let moneyIcon = NSTextAttachment()
// If you're sure a value is not and will never be nil, you can use "!".
// Otherwise, avoid it.
let moneyImage = UIImage(named: "MoneyIcon")!
moneyIcon.image = moneyImage
let moneyIconString = NSAttributedString(attachment: moneyIcon)
// *Setting up NSAttributedString attributes*
let balanceFontSize: CGFloat = 16
let balanceFont = UIFont(name: "Baloo", size: balanceFontSize)!
let balanceBaselineOffset: CGFloat = {
let dividend = moneyImage.size.height - balanceFontSize
return dividend / 2 - balanceFont.descender / 2
}()
let balanceAttr: [NSAttributedString.Key: Any] = [
.font: balanceFont,
.baselineOffset: balanceBaselineOffset
]
// *Setting up text*
let balanceString = NSMutableAttributedString(
string: " 1,702,200",
attributes: balanceAttr
)
balanceString.insert(moneyIconString, at: 0)