I’m trying to add a rounded background with padding to attributed text. While I’ve successfully implemented the rounded background with padding, I’m facing challenges in aligning the attachment precisely with the text.
final class TextUViewController: UIViewController {
private lazy var label: UILabel = {
let label = UILabel()
label.numberOfLines = 2
label.backgroundColor = .red.withAlphaComponent(0.3)
return label
}()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .black
view.addSubview(label)
label.translatesAutoresizingMaskIntoConstraints = false
label.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 15).isActive = true
label.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -15).isActive = true
label.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
label.attributedText = createAttributedText()
}
func createAttributedText() -> NSAttributedString {
let text = "It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old."
let token = "2000"
let attributedString = NSMutableAttributedString(string: text)
let baseAttributes: [NSAttributedString.Key: Any] = [
.foregroundColor: UIColor.green,
.font: UIFont.systemFont(ofSize: 14, weight: .medium),
.baselineOffset: 0,
]
let baseRange = NSRange(location: 0, length: attributedString.length)
attributedString.addAttributes(baseAttributes, range: baseRange)
if let range = text.range(of: token) {
let nsRange = NSRange(range, in: text)
let attachment = createAttachment()
let attachmentString = NSAttributedString(attachment: attachment)
attributedString.replaceCharacters(in: nsRange, with: attachmentString)
}
return attributedString
}
func createAttachment() -> NSTextAttachment {
let label = UILabel()
label.text = "2000"
label.textColor = .blue
label.backgroundColor = .white
label.font = UIFont.systemFont(ofSize: 14, weight: .bold)
label.layer.cornerRadius = 2
label.layer.masksToBounds = true
label.textAlignment = .center
label.sizeToFit()
let width = label.bounds.width + 12
let height = label.bounds.height + 6
label.bounds = .init(
x: 0,
y: 0,
width: width,
height: height
)
let renderer = UIGraphicsImageRenderer(size: label.bounds.size)
let image = renderer.image { context in
label.layer.render(in: context.cgContext)
}
let attachment = NSTextAttachment()
attachment.image = image
return attachment
}
}
Do you have any suggestions to solve this problem, or do you have an alternative solution for adding a rounded background to attributed text?
I’ve tried using baselineOffset
to fix the alignment issue, but then the text doesn’t behave correctly in multiline scenarios.
with baselineOffset: 0
multi line
with baselineOffset: 6
multi line
with baselineOffset: 6
single line (This is what I want to achieve in both single and multiline texts.)