5

使用 Swift,我想在 UILabel 中的 draw#rect 中获取字形的 boundingRect。

UILabel 已经具有大小(例如示例中的 300x300)和质量,例如居中的文本。

class RNDLabel: UILabel {

    override func draw(_ rect: CGRect) {

        let manager = NSLayoutManager()

        let store = NSTextStorage(attributedString: NSAttributedString(
            string: text!,
            attributes: [NSAttributedString.Key.font: font]))
        store.addLayoutManager(manager)

        let textContainer = NSTextContainer(size: rect.size)
        // note, intrinsicContentSize is identical there, no difference
        manager.addTextContainer(textContainer)

        let glyphRange = manager.glyphRange(
           forCharacterRange: NSRange(location: 0, length: 1),
           actualCharacterRange: nil)
        let glyphRect = manager.boundingRect(
           forGlyphRange: glyphRange, in: textContainer)

        print("glyphRect \(glyphRect)")         
        ...context?.addRect(glyphRect), context?.drawPath(using: .stroke)

        super.draw(rect)
    }

在此处输入图像描述

绿色方块不正确——它应该更像这些红色方块!

在此处输入图像描述

似乎有很多问题:

  • 当然,我制作的 layoutManager 应该具有 UILabel 的品质,例如“居中文本”?(不过,我相信您实际上不能直接访问 UILabel 的 layoutManager 吗?)

  • 我们应该使用 CTLineGetOffsetForStringIndex 之类的东西吗?在draw#rect中甚至可能吗

  • 请注意,除了没有正确的偏移量外,绿框似乎还是错误的高度。(它看起来更像是一个普通的旧的 intrinsicContentSize 而不是字形边界框。)

如何?

作为记录,我的总体目标是根据实际的字形框移动字形(对于“y”、“X”等当然是不同的)。但总的来说,有很多有用的理由来了解字形的框。

4

2 回答 2

1

你最初的问题是一个没有问题的问题,因为它说的是两个完全相反的事情。

  • 一方面,你说 UILabel。

  • 另一方面,您使用诸如 NSLayoutManager 和 NSTextStorage 和 NSTextContainer 之类的术语——TextKit 堆栈。

这些是相反的,因为 UILabel 不是使用 TextKit 堆栈绘制的。所以你要求做的就像试图用磁铁举起一张纸;磁铁确实能提升东西,但它们提升的是磁性材料,而纸不是其中之一。可以肯定的是,UILabel 必须以某种确定性的方式绘制,但这种方式是什么,完全未知且不透明,与 TextKit 无关。

另一方面,UITextView 或您使用 TextKit 自己绘制的视图确实使用了 TextKit,现在所有的 TextKit 工具都适用。因此,如果这是一个 UITextView(或您使用 TextKit 自己绘制的视图),那么您要求做的事情会更加直接。

这不需要对界面的外观有太大的改变。可以使 UITextView 的行为与 UILabel 非常相似(使其不可编辑和不可滚动),但重要的区别是整个文本工具包堆栈直接公开。这就是我要开始的地方。我是那些喜欢使用框架而不是与之抗争的人之一。

于 2019-07-17T15:52:34.823 回答
0

事实证明,这个问题的答案似乎是:

事实上,无论是否令人惊讶,您基本上都无法访问 UILabel 中的字形信息。

所以实际上你无法在 UILabel 中获得那些字形“实际形状”。

特别是 RobN。曾指出,一项调查表明,在 UILabel 中,_drawTextInRect:baselineCalculationOnly 完成了这项工作,这是一大堆临时代码。

情况的总结似乎是 UILabel 只是早于 NSLayoutManager / Core Text 并且(到目前为止)只是简单地不使用那些现代系统。

只有那些现代系统才能给你这个......

在此处输入图像描述

... 对字形逐个字形的访问。

于 2019-07-15T11:02:22.663 回答