使用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
注意以及没有正确的偏移量,无论如何,绿色框似乎是错误的高度。 (它看起来更像是一个普通的旧的internalContentSize,而不是一个字形边界框。)
如何?
FTR我的总体目标是根据实际字形框移动字形(当然,“ y”,“ X”等也不同)。但是总的来说,有很多有用的原因来了解字形的框。
答案 0 :(得分:0)
事实证明,这个问题的答案似乎是:
尤其是RobN。已经指出,一项调查表明,在UILabel中,_drawTextInRect:baselineCalculationOnly可以完成这项工作,并且是一大堆临时代码。
这种情况的总结似乎是UILabel早于NSLayoutManager / Core Text,并且(到目前为止)仅使用了这些现代系统。
只有那些现代系统才能为您提供...
...可以逐字形地访问字形。
答案 1 :(得分:0)
您最初的问题是一个毫无疑问的问题,因为它说了两个完全相反的事情。
一方面,您说的是UILabel。
另一方面,您使用诸如NSLayoutManager和NSTextStorage和NSTextContainer之类的术语-TextKit堆栈。
相反,因为UILabel不是用TextKit堆栈绘制的。因此,您要执行的操作就像尝试用磁铁提起一张纸一样。磁铁确实可以举起东西,但是它们举起的是磁性材料,而纸不是其中之一。可以肯定的是,UILabel必须以某种确定性的方式绘制,但是这是什么完全未知且不透明,与TextKit无关。
另一方面,UITextView或使用TextKit绘制的视图,确实使用TextKit,现在所有TextKit工具都适用。因此,如果这个是 UITextView(或您使用TextKit绘制的视图),那么您要要做的事情就简单得多。
这不需要太多改变界面的外观。可以使UITextView像UILabel一样工作(使其不可编辑且不可滚动),但重要的区别在于整个文本工具包堆栈都直接公开。这就是我要开始的地方。我就是那些更喜欢使用而不是战斗的人之一。