You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用NSAttributedString设置文字描边时,字符2、6显示异常求助

字符描边显示异常的原因与解决方法

问题原因

当strokeWidth设为负数时,CoreText会先绘制白色描边,再用前景色填充字符内部。但系统黑粗体中“2”“6”这类带闭合区域的字符,填充操作会覆盖闭合区域内的描边,导致这些字符的内部描边消失,显示异常。

解决方法

方法1:使用双层UILabel叠加

创建两个UILabel,分别处理描边和填充,将填充Label放在描边Label上方:

override func viewDidLoad() {
    super.viewDidLoad()
    
    // 描边Label(底层)
    let strokeLabel = UILabel()
    strokeLabel.frame = CGRect(x: 20, y: 100, width: 400, height: 100)
    strokeLabel.font = UIFont.systemFont(ofSize: 88, weight: .black)
    let strokeAttrs: [NSAttributedString.Key: Any] = [
        .strokeWidth: 2,
        .strokeColor: UIColor.white
    ]
    strokeLabel.attributedText = NSAttributedString(string: "123456", attributes: strokeAttrs)
    view.addSubview(strokeLabel)
    
    // 填充Label(上层)
    let fillLabel = UILabel()
    fillLabel.frame = strokeLabel.frame
    fillLabel.font = strokeLabel.font
    fillLabel.textColor = .orange
    fillLabel.text = "123456"
    view.addSubview(fillLabel)
}

方法2:自定义UILabel重写绘制逻辑

通过重写drawText(in:)方法,先绘制描边再绘制填充,确保描边不被覆盖:

class StrokeLabel: UILabel {
    /// 描边颜色
    var strokeColor: UIColor = .white
    /// 描边宽度
    var strokeWidth: CGFloat = 2
    
    override func drawText(in rect: CGRect) {
        guard let text = text, let font = font else {
            super.drawText(in: rect)
            return
        }
        // 配置描边属性
        let strokeAttributes: [NSAttributedString.Key: Any] = [
            .strokeColor: strokeColor,
            .strokeWidth: strokeWidth,
            .font: font
        ]
        // 先绘制描边
        text.draw(in: rect, withAttributes: strokeAttributes)
        // 再绘制填充
        super.drawText(in: rect)
    }
}

使用自定义Label的代码:

override func viewDidLoad() {
    super.viewDidLoad()
    
    let testLabel = StrokeLabel()
    testLabel.frame = CGRect(x: 20, y: 100, width: 400, height: 100)
    testLabel.font = UIFont.systemFont(ofSize: 88, weight: .black)
    testLabel.textColor = .orange
    testLabel.strokeColor = .white
    testLabel.strokeWidth = 2
    testLabel.text = "123456"
    view.addSubview(testLabel)
}

内容的提问来源于stack exchange,提问作者ImWH

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 20:19:01