【问题标题】:How to define a custom NSUnderlineStyle如何定义一个自定义的 NSUnderlineStyle
【发布时间】:2016-03-25 11:04:35
【问题描述】:

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

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

我的问题是:这到底是怎么做的?

NSUnderlineStyle 是一个枚举,不能扩展或覆盖。您当然可以为该属性提供一个随机的原始 Int 值,枚举案例未涵盖:

self.addAttribute(NSUnderlineStyleAttributeName, value: 100022, range: lastUpdatedWordRange)

这将向布局管理器提供“无效”但可用的underlineType

但这让人感觉不安全,而且绝对不雅。

我无法在网上找到任何示例,也无法在 Apple 文档中找到有关这些神话般的自定义下划线样式类型的进一步线索。我很想知道我是否遗漏了一些明显的东西。

【问题讨论】:

  • NSUnderlineStyle 似乎是一个糟糕的团队合作者。它的文档记录很差,而且在 Swift 中,它仍然没有被转换为选项集。在以给定样式读取标志时,它似乎不可靠(否则我做错了什么)。希望我能提供更多帮助,但我仍在研究解决方案...

标签: ios swift nsattributedstring textkit nslayoutmanager


【解决方案1】:

我在这里有一个示例项目,用于在 TextKit 上进行一次演讲,该项目完全符合您的要求:https://github.com/dtweston/text-kit-example

本例中的下划线是波浪线:

解决方案的核心是自定义 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)
        }
    }
}

【讨论】:

    猜你喜欢
    • 2013-07-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-01
    • 1970-01-01
    相关资源
    最近更新 更多