在UILabel的draw#rect中获取字形boundingRect。胖赏金

时间:2019-07-08 13:23:05

标签: ios swift drawrect nslayoutmanager

使用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)
    }

enter image description here

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

enter image description here

似乎有很多问题...

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

  • 我们应该使用类似CTLineGetOffsetForStringIndex的东西吗?在draw#rect

  • 中甚至可能
  • 注意以及没有正确的偏移量,无论如何,绿色框似乎是错误的高度。 (它看起来更像是一个普通的旧的internalContentSize,而不是一个字形边界框。)

如何?

FTR我的总体目标是根据实际字形框移动字形(当然,“ y”,“ X”等也不同)。但是总的来说,有很多有用的原因来了解字形的框。

2 个答案:

答案 0 :(得分:0)

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

实际上,无论您是否出乎意料,您基本上没有 no 专门访问UILabel中的字形信息。

实际上,您无法在UILabel中获得这些字形“实际形状”。

尤其是RobN。已经指出,一项调查表明,在UILabel中,_drawTextInRect:baselineCalculationOnly可以完成这项工作,并且是一大堆临时代码。

这种情况的总结似乎是UILabel早于NSLayoutManager / Core Text,并且(到目前为止)仅使用了这些现代系统。

只有那些现代系统才能为您提供...

enter image description here

...可以逐字形地访问字形。

答案 1 :(得分:0)

您最初的问题是一个毫无疑问的问题,因为它说了两个完全相反的事情。

  • 一方面,您说的是UILabel。

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

相反,因为UILabel不是用TextKit堆栈绘制的。因此,您要执行的操作就像尝试用磁铁提起一张纸一样。磁铁确实可以举起东西,但是它们举起的是磁性材料,而纸不是其中之一。可以肯定的是,UILabel必须以某种确定性的方式绘制,但是这是什么完全未知且不透明,与TextKit无关。

另一方面,UITextView或使用TextKit绘制的视图,确实使用TextKit,现在所有TextKit工具都适用。因此,如果这个 UITextView(或您使用TextKit绘制的视图),那么您要要做的事情就简单得多。

这不需要太多改变界面的外观。可以使UITextView像UILabel一样工作(使其不可编辑且不可滚动),但重要的区别在于整个文本工具包堆栈都直接公开。这就是我要开始的地方。我就是那些更喜欢使用而不是战斗的人之一。