iOS:在文本标签周围绘制边框

iOS:在文本标签周围绘制边框,ios,uilabel,border,nsattributedstring,Ios,Uilabel,Border,Nsattributedstring,我想在UILabel的文本周围画一个轮廓,如下所示: 我尝试使用属性文本,但没有用于渲染文本周围边框的属性。只有下划线可用。我还尝试使用属性文本呈现html,但也没有帮助: let htmlLabelText = String(format: "<html><body><span style='color:blue; border: 1.5px solid #55DF49; border-radius: 50px;'>%@</span></

我想在
UILabel
的文本周围画一个轮廓,如下所示:

我尝试使用属性文本,但没有用于渲染文本周围边框的属性。只有下划线可用。我还尝试使用属性文本呈现html,但也没有帮助:

let htmlLabelText = String(format: "<html><body><span style='color:blue; border: 1.5px solid #55DF49; border-radius: 50px;'>%@</span></body></html>", labelText)
var attributedString = NSMutableAttributedString()
guard let stringData = data(using: .unicode) else { return NSMutableAttributedString() }
do {
    attributedString = try NSMutableAttributedString(
        data: stringData,
        options: [NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType],
        documentAttributes: nil
    )
} catch {}
让htmlLabelText=字符串(格式:“%@”,labelText)
var attributedString=NSMutableAttributedString()
guard let stringData=data(使用:.unicode)else{return NSMutableAttributedString()}
做{
attributedString=尝试NSMutableAttributedString(
数据:stringData,
选项:[NSDocumentTypeDocumentAttribute:NSHTMLTextDocumentType],
文件属性:无
)
}捕获{}
我查看了其他帖子,但没有一篇有用。

以下是答案

label1.layer.borderColor = [UIColor greenColor].CGColor;
label1.layer.borderWidth =1.0


尝试这些不同的可能性。

UILabel的问题很难解决,因为您无法直接访问NSLayoutManager,这是我的解决方案的关键

我已经创建了IBDesignable UILabel子类LineHighlightedLabel,它可以完成这项工作。视觉效果与您提供的图像不完全相同,但您可以到达那里

重要的部分是将UILabel中的文本设置为NSAttribute字符串,而不仅仅是纯文本

@IBDesignable
public class LineHighlightedLabel: UILabel {
    public override func draw(_ rect: CGRect) {
        let layoutManager = NSLayoutManager()
        let textStorage = NSTextStorage.init(attributedString: attributedText!)
        textStorage.addLayoutManager(layoutManager)

        let textContainer = NSTextContainer.init(size: bounds.size)
        textContainer.lineFragmentPadding  = 0
        textContainer.maximumNumberOfLines = numberOfLines
        textContainer.lineBreakMode        = lineBreakMode

        layoutManager.addTextContainer(textContainer)

        layoutManager.enumerateLineFragments(forGlyphRange: NSMakeRange(0, textStorage.length)) { (rect, usedRect, textContainer, glyphRange, bool) in
            let lineRect = CGRect(x: usedRect.origin.x, y: usedRect.origin.y + 1, width: usedRect.size.width, height: usedRect.size.height - 2)
            UIColor.green.setStroke()
            let lineRectPath = UIBezierPath(roundedRect: lineRect, cornerRadius: 5)
            lineRectPath.lineWidth = 0.5
            lineRectPath.stroke()
        }

        super.drawText(in: rect)
    }

    public override func layoutSubviews() {
        super.layoutSubviews()
        setNeedsDisplay()
    }
}
LineHighlightedLabel在界面生成器中提供了很好的预览,您可以轻松地使用值


@shota的答案同样有效

这正是我在不使用NSLayoutManager的情况下通过子类化UILabel解决问题的方法。虽然使用LayoutManager.enumerateLineFragments是更好的选择,但我复制了用于从stackoverflow中的某个地方的文本中获取行的代码。此外,还需要一种技巧来呈现UILabel的文本,在开始和结束处有两个空格。以下是最终结果的屏幕截图:


展示你的requirement@Vinodh我希望它看起来像第一张照片,一张文本周围有绿色边框的照片。它是一个标签,可以有任意数量的线条。
label3.layer.borderWidth = 2.0;
label3.layer.cornerRadius = 8;
@IBDesignable
public class LineHighlightedLabel: UILabel {
    public override func draw(_ rect: CGRect) {
        let layoutManager = NSLayoutManager()
        let textStorage = NSTextStorage.init(attributedString: attributedText!)
        textStorage.addLayoutManager(layoutManager)

        let textContainer = NSTextContainer.init(size: bounds.size)
        textContainer.lineFragmentPadding  = 0
        textContainer.maximumNumberOfLines = numberOfLines
        textContainer.lineBreakMode        = lineBreakMode

        layoutManager.addTextContainer(textContainer)

        layoutManager.enumerateLineFragments(forGlyphRange: NSMakeRange(0, textStorage.length)) { (rect, usedRect, textContainer, glyphRange, bool) in
            let lineRect = CGRect(x: usedRect.origin.x, y: usedRect.origin.y + 1, width: usedRect.size.width, height: usedRect.size.height - 2)
            UIColor.green.setStroke()
            let lineRectPath = UIBezierPath(roundedRect: lineRect, cornerRadius: 5)
            lineRectPath.lineWidth = 0.5
            lineRectPath.stroke()
        }

        super.drawText(in: rect)
    }

    public override func layoutSubviews() {
        super.layoutSubviews()
        setNeedsDisplay()
    }
}