I used one different way. First I get all lines from the UILabel
and add extra blank space at the starting position of every line. To getting all line from the UILabel
I just modify code from this link (https://stackoverflow.com/a/55156954/14733292)
Final extension UILabel
code:
extension UILabel {
var addWhiteSpace: String {
guard let text = text, let font = font else { return "" }
let ctFont = CTFontCreateWithName(font.fontName as CFString, font.pointSize, nil)
let attStr = NSMutableAttributedString(string: text)
attStr.addAttribute(kCTFontAttributeName as NSAttributedString.Key, value: ctFont, range: NSRange(location: 0, length: attStr.length))
let frameSetter = CTFramesetterCreateWithAttributedString(attStr as CFAttributedString)
let path = CGMutablePath()
path.addRect(CGRect(x: 0, y: 0, width: self.frame.size.width, height: CGFloat.greatestFiniteMagnitude), transform: .identity)
let frame = CTFramesetterCreateFrame(frameSetter, CFRangeMake(0, 0), path, nil)
guard let lines = CTFrameGetLines(frame) as? [Any] else { return "" }
return lines.map { line in
let lineRef = line as! CTLine
let lineRange: CFRange = CTLineGetStringRange(lineRef)
let range = NSRange(location: lineRange.location, length: lineRange.length)
return " " + (text as NSString).substring(with: range)
}.joined(separator: "\n")
}
}
Use:
let labelText = yourLabel.addWhiteSpace
let attributedString = NSMutableAttributedString(string: labelText)
attributedString.addAttribute(NSAttributedString.Key.backgroundColor, value: UIColor.red, range: NSRange(location: 0, length: labelText.count))
yourLabel.attributedText = attributedString
yourLabel.backgroundColor = .yellow
Edited:
The above code is worked at some point but it's not sufficient. So I created one class and added padding and one shape rect layer.
class AttributedPaddingLabel: UILabel {
private let leftShapeLayer = CAShapeLayer()
var leftPadding: CGFloat = 5
var attributedTextColor: UIColor = .red
override func awakeFromNib() {
super.awakeFromNib()
self.addLeftSpaceLayer()
self.addAttributed()
}
override func drawText(in rect: CGRect) {
let insets = UIEdgeInsets(top: 0, left: leftPadding, bottom: 0, right: 0)
super.drawText(in: rect.inset(by: insets))
}
override var intrinsicContentSize: CGSize {
let size = super.intrinsicContentSize
return CGSize(width: size.width + leftPadding, height: size.height)
}
override var bounds: CGRect {
didSet {
preferredMaxLayoutWidth = bounds.width - leftPadding
}
}
override func draw(_ rect: CGRect) {
super.draw(rect)
leftShapeLayer.path = UIBezierPath(rect: CGRect(x: 0, y: 0, width: leftPadding, height: rect.height)).cgPath
}
private func addLeftSpaceLayer() {
leftShapeLayer.fillColor = attributedTextColor.cgColor
self.layer.addSublayer(leftShapeLayer)
}
private func addAttributed() {
let lblText = self.text ?? ""
let attributedString = NSMutableAttributedString(string: lblText)
attributedString.addAttribute(NSAttributedString.Key.backgroundColor, value: attributedTextColor, range: NSRange(location: 0, length: lblText.count))
self.attributedText = attributedString
}
}
How to use:
class ViewController: UIViewController {
@IBOutlet weak var lblText: AttributedPaddingLabel!
override func viewDidLoad() {
super.viewDidLoad()
lblText.attributedTextColor = .green
lblText.leftPadding = 10
}
}