2016-07-27 2 views
3

Я показываю текст, который может содержать emoji с использованием метода NSAttributedStringdrawInRect(rect: CGRect). Так как я хочу, чтобы обнаружить краны по тексту я использую следующий метод, чтобы увидеть, какой символ был постучали:NSLayoutManager, boundingRectForGlyphRange и emoji

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) 

Это дает правильный индекс, что я могу работать с тем, пока я не начинаю добавлять смайлик к тексту. Как только emoji добавляется, начинается смещение для обнаружения. Это заставило меня взглянуть на ограничивающие прямоугольники глифов, которые я искал. Я заметил, что ограничивающие прямоугольники эможи слишком велики. Я создал следующий тест, чтобы проверить разницу:

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 S:

glyphRect = (0.0, 0.0, 23.0, 28.875) 
boundingRect = (0.0, 0.0, 23.0, 23.8671875) 

Что это означает, что эти два метода дают два совершенно разных размеров! Это не проблема, но «офсетные» стеки с большим количеством строк.

Example of the stacked offset

Я поставил фиолетовый фон для характера characterIndexForPoint дал мне, дал прямоугольник из boundingRectForGlyphRange зеленый контур и желтая точка является фактическим taplocation. Обратите внимание, что зеленый прямоугольник хорошо сочетается с другим персонажем, однако это не является признаком того, что происходит, поскольку в этом конкретном случае это происходит просто.

Я пропустил что-то очевидное или это проблема в iOS?

ответ

1

Я решил проблему. Похоже, что NSAttributedString.drawInRect рисует иначе, чем CoreText. Теперь я использую следующий код, чтобы нарисовать текст в drawRect:

let totalRange = layoutManager.glyphRangeForTextContainer(textContainer) 

layoutManager.drawBackgroundForGlyphRange(range, atPoint: CGPointZero) 
layoutManager.drawGlyphsForGlyphRange(range, atPoint: CGPointZero) 
Смежные вопросы