如何定义自定义NSUnderlineStyle

7
查看NSLayoutManager的文档,特别是drawUnderlineForGlyphRange:underlineType:baselineOffset:lineFragmentRect:lineFragmentGlyphRange:containerOrigin:方法时,我注意到以下内容(重点是我的):

underlineVal
要绘制的下划线风格。此值是从NSUnderlineStyleAttributeName的值派生的掩码,例如(NSUnderlinePatternDash | NSUnderlineStyleThick )。子类可以定义自定义下划线样式。

我的问题是:这应该如何完成? NSUnderlineStyle是一个枚举类型,您无法扩展或覆盖它。当然,您可以为该属性提供随机的Int值,不包含在枚举情况中: self.addAttribute(NSUnderlineStyleAttributeName, value: 100022, range: lastUpdatedWordRange) 这将向排版管理器提供“无效”但可用的underlineTypedebugger screenshot 但是这几乎感觉不安全,而且绝对不优雅。
我无法在网上找到任何示例或在苹果文档中找到关于那些神秘的自定义下划线样式类型的进一步线索。如果我错过了明显的东西,我很想知道。

您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - definitelyokay
1个回答

5
我这里有一个例子项目,我曾用它来做关于TextKit的演讲,它恰好可以做到你所需的功能:https://github.com/dtweston/text-kit-example 在这种情况下下划线是一条波浪线: underline screenshot 解决方案的核心是一个自定义的NSLayoutManager:
let CustomUnderlineStyle = 0x11

class UnderlineLayoutManager: NSLayoutManager {
    
    func drawFancyUnderlineForRect(_ rect: CGRect) {
        let left = rect.minX
        let bottom = rect.maxY
        let width = rect.width
        
        let path = UIBezierPath()
        path.move(to: CGPoint(x: left, y: bottom))
        var x = left
        var y = bottom
        var i = 0
        while (x <= left + width) {
            path.addLine(to: CGPoint(x: x, y: y))
            x += 2
            if i % 2 == 0 {
                y = bottom + 2.0
            }
            else {
                y = bottom
            }
            i += 1;
        }
        
        path.stroke()
    }
    
    override func drawUnderline(forGlyphRange glyphRange: NSRange, underlineType underlineVal: NSUnderlineStyle, baselineOffset: CGFloat, lineFragmentRect lineRect: CGRect, lineFragmentGlyphRange lineGlyphRange: NSRange, containerOrigin: CGPoint) {
        
        if underlineVal.rawValue & CustomUnderlineStyle == CustomUnderlineStyle {
            
            let charRange = characterRange(forGlyphRange: glyphRange, actualGlyphRange: nil)
            if let underlineColor = textStorage?.attribute(NSUnderlineColorAttributeName, at: charRange.location, effectiveRange: nil) as? UIColor {
                underlineColor.setStroke()
            }
            
            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)
                
                drawFancyUnderlineForRect(offsetRect)
            }
        }
        else {
            super.drawUnderline(forGlyphRange: glyphRange, underlineType: underlineVal, baselineOffset: baselineOffset, lineFragmentRect: lineRect, lineFragmentGlyphRange: lineGlyphRange, containerOrigin: containerOrigin)
        }
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接