我使用NSAttributedString的drawInRect(rect: CGRect)方法显示可能包含表情符号的文本。因为我想检测文本上的点击,所以我使用以下方法来查看哪个字符被点击:
let textStorage = NSTextStorage(attributedString: attributedString)
let layoutManager = NSLayoutManager()
layoutManager.usesFontLeading = true
textStorage.addLayoutManager(layoutManager)
let textContainer = NSTextContainer(size: containerSize)
layoutManager.addTextContainer(textContainer)
textContainer.lineFragmentPadding = 0.0
layoutManager.ensureLayoutForTextContainer(textContainer)
let tappedIndex = layoutManager.characterIndexForPoint(point,
inTextContainer: textContainer,
fractionOfDistanceBetweenInsertionPoints: nil)这给出了我可以使用的正确索引,直到我开始在文本中添加表情符号。一旦添加了表情符号,就会开始出现检测偏移量。这使我开始查看我正在寻找的字形的边界矩形。我注意到表情符号的边框太大了。我设置了以下测试用例来检查差异:
let emojiText = ""
let font = UIFont.systemFontOfSize(20.0)
let containerSize = CGSize(width: 300.0, height: 20000.0)
let attributedString = NSAttributedString(string: emojiText, attributes: [NSFontAttributeName: font])
let textStorage = NSTextStorage(attributedString: attributedString)
let layoutManager = NSLayoutManager()
layoutManager.usesFontLeading = true
textStorage.addLayoutManager(layoutManager)
let textContainer = NSTextContainer(size: containerSize)
layoutManager.addTextContainer(textContainer)
textContainer.lineFragmentPadding = 0.0
layoutManager.ensureLayoutForTextContainer(textContainer)
let glyphRect = layoutManager.boundingRectForGlyphRange(NSRange(location: 0, length: attributedString.length), inTextContainer: textContainer)
let boundingRect = attributedString.boundingRectWithSize(containerSize, options:[.UsesLineFragmentOrigin, .UsesFontLeading], context: nil)执行此代码会导致以下CGRect:
glyphRect = (0.0, 0.0, 23.0, 28.875)
boundingRect = (0.0, 0.0, 23.0, 23.8671875)这意味着这两种方法提供了两种完全不同的大小!这不是问题,但是'offset‘堆栈有更多的行。
Example of the stacked offset
我为characterIndexForPoint给我的字符设置了紫色背景,给boundingRectForGlyphRange的矩形画了一个绿色的轮廓,黄点是实际的位置。请注意,绿色矩形与不同的字符对齐得很好,然而,这并不是任何指示,因为在这个特定的情况下,它恰好对齐。
我是否忽略了一些显而易见的东西,或者这是iOS中的一个问题?
发布于 2016-07-28 22:45:07
我已经解决了这个问题。看起来NSAttributedString.drawInRect和CoreText的绘制方式不同。我现在使用以下代码在drawRect中绘制文本
let totalRange = layoutManager.glyphRangeForTextContainer(textContainer)
layoutManager.drawBackgroundForGlyphRange(range, atPoint: CGPointZero)
layoutManager.drawGlyphsForGlyphRange(range, atPoint: CGPointZero)https://stackoverflow.com/questions/38619395
复制相似问题