如何在文本 UILabel 周围实现粗描边边框

Xax*_*xus 5 core-graphics uikit nsattributedstring uilabel swift

这就是我想要实现的目标:

在此输入图像描述

这是我尝试过的一些事情:

NS属性字符串

我尝试使用NSAttributedString以下属性,但 iOS 14+ 中的文本路径似乎存在错误

private var attributes: [NSAttributedString.Key: Any] {
    [
        .strokeColor : strokeColor,
        .strokeWidth : -8,
        .foregroundColor : foregroundColor,
        .font: UIFont.systemFont(ofSize: 17, weight: .black)
    ]
}
Run Code Online (Sandbox Code Playgroud)

NS属性字符串

NSAttributedString如果某些字母没有出现奇怪的路径问题,我对这个结果非常满意。

绘制文本覆盖

我也尝试过覆盖drawText,但据我所知,我找不到任何方法来改变笔划粗细并将其与下一个字符混合在一起:

override func drawText(in rect: CGRect) {
    let context = UIGraphicsGetCurrentContext()
    context?.setLineJoin(.round)
    
    context?.setTextDrawingMode(.stroke)
    self.textColor = strokeColor
    super.drawText(in: rect)
    
    context?.setTextDrawingMode(.fill)
    self.textColor = foregroundColor
    super.drawText(in: rect)
    
    layer.shadowColor = UIColor.black.cgColor
    layer.shadowRadius = 2
    layer.shadowOpacity = 0.08
    layer.shadowOffset = .init(width: 0, height: 2)
}
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

RTX*_*mer 5

使用这个可设计的类在故事板上用笔画渲染标签。我尝试的大多数字体看起来都很糟糕(带有CGLineJoin.miter),我发现“PingFang TC”字体最接近所需的输出。尽管CGLineJoin.roundlineJoin 在大多数字体上看起来都很好。

@IBDesignable
class StrokeLabel: UILabel {
    @IBInspectable var strokeSize: CGFloat = 0
    @IBInspectable var strokeColor: UIColor = .clear
  
    override func drawText(in rect: CGRect) {
        let context = UIGraphicsGetCurrentContext()
        let textColor = self.textColor
        context?.setLineWidth(self.strokeSize)
        context?.setLineJoin(CGLineJoin.miter)
        context?.setTextDrawingMode(CGTextDrawingMode.stroke)
        self.textColor = self.strokeColor
        super.drawText(in: rect)
        context?.setTextDrawingMode(.fill)
        self.textColor = textColor
        super.drawText(in: rect)
    }
}
Run Code Online (Sandbox Code Playgroud)

输出:(检查属性检查器中使用的值以供参考)

在此输入图像描述