According to Eiko&Dave's answer, i made an example like this
i've try to finish that by using UILabel rather than UITextView, but could not find a solution after searching from stackoverflow or other websites. So, i used UITextView to do that.
let storage = NSTextStorage()
let layout = UnderlineLayout()
storage.addLayoutManager(layout)
let container = NSTextContainer()
container.widthTracksTextView = true
container.lineFragmentPadding = 0
container.maximumNumberOfLines = 2
container.lineBreakMode = .byTruncatingTail
layout.addTextContainer(container)
let textView = UITextView(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width-40, height: 50), textContainer: container)
textView.isUserInteractionEnabled = true
textView.isEditable = false
textView.textContainerInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
textView.text = "1sadasdasdasdasdsadasdfdsf"
textView.backgroundColor = UIColor.white
let rg = NSString(string: textView.text!).range(of: textView.text!)
let attributes = [NSAttributedString.Key.underlineStyle.rawValue: 0x11,
NSAttributedString.Key.underlineColor: UIColor.blue.withAlphaComponent(0.2),
NSAttributedString.Key.foregroundColor: UIColor.black, NSAttributedString.Key.font: UIFont.systemFont(ofSize: 17),
NSAttributedString.Key.baselineOffset:10] as! [NSAttributedString.Key : Any]
storage.addAttributes(attributes, range: rg)
view.addSubview(textView)
override LayoutManage Method
class UnderlineLayout: NSLayoutManager {
override func drawUnderline(forGlyphRange glyphRange: NSRange, underlineType underlineVal: NSUnderlineStyle, baselineOffset: CGFloat, lineFragmentRect lineRect: CGRect, lineFragmentGlyphRange lineGlyphRange: NSRange, containerOrigin: CGPoint) {
if let container = textContainer(forGlyphAt: glyphRange.location, effectiveRange: nil) {
let boundingRect = self.boundingRect(forGlyphRange: glyphRange, in: container)
let offsetRect = boundingRect.offsetBy(dx: containerOrigin.x, dy: containerOrigin.y)
let left = offsetRect.minX
let bottom = offsetRect.maxY-15
let width = offsetRect.width
let path = UIBezierPath()
path.lineWidth = 3
path.move(to: CGPoint(x: left, y: bottom))
path.addLine(to: CGPoint(x: left + width, y: bottom))
path.stroke()
}
}
in my solution, i've to expand lineSpacing also keep a customize underline by using NSAttributedString property NSMutableParagraphStyle().lineSpacing, but it seems that didn't work, but NSAttributedString.Key.baselineOffset is worked. hope can