I want to implement a UITextView whose content consists of plain text and tags, where the tags are text with a rounded gray background.
I tried to use NSAttributedString, but it cannot set rounded background.
Any idea? Thanks in advance.
You can implement by generating an Image using CoreGraphics and wrapping it inside a NSTextAttachment
.
For example, here's an implementation as an extension of String
:
extension String {
func generateImage(_ size: CGSize,
textFont: UIFont = .systemFont(ofSize: 16),
textColor: UIColor = .white,
fillColor: UIColor = .brown) -> NSAttributedString {
let format = UIGraphicsImageRendererFormat()
format.scale = UIScreen.main.scale
let render = UIGraphicsImageRenderer(size: size, format: format)
let image = render.image { context in
let ellipsePath = UIBezierPath(roundedRect: CGRect(origin: .zero, size: size), cornerRadius: size.height / 2).cgPath
context.cgContext.setFillColor(fillColor.cgColor)
context.cgContext.addPath(ellipsePath)
context.cgContext.fillPath()
let attributed = NSAttributedString(string: self, attributes: [.font: textFont, .foregroundColor: textColor])
let textSize = attributed.size()
attributed.draw(at: CGPoint(x: (size.width - textSize.width) / 2, y: (size.height - textSize.height) / 2))
}
let attachment = NSTextAttachment(data: nil, ofType: nil)
attachment.image = image
attachment.bounds = .init(x: 0, y: -9.3125, width: size.width, height: size.height)
attachment.lineLayoutPadding = 5
return .init(attachment: attachment)
}
}
Then when you want to use it:
// Your UITextView with an attributed string
let view = UITextView()
view.attributedText = testAttributedString()
// An example usage
func testAttributedString() -> NSAttributedString {
let test = NSMutableAttributedString()
test.append(.init(string: "How"))
test.append("are".generateImage(.init(width: 60, height: 30)))
test.append(.init(string: "you"))
return test
}
Here's an example on how it looks