IPhone CoreText: найдите пиксельные координаты подстроки

Вот скриншот приложения twitter для справки: http://screencast.com/t/YmFmYmI4M

То, что я хочу сделать, это разместить плавающий всплывающий над подстрокой в ​​NSAttributedString, который может охватывать несколько строк. NSAttributedString является обязательным для проекта.

В представленном скриншоте вы можете видеть, что ссылки выделены фоном, поэтому мне кажется, что они используют CoreText и NSAttributedStrings. Я также нашел что-то, называемое CTRunRef (http://developer.apple.com/library/ios/#documentation/Carbon/Reference/CTRunRef/Reference/reference.html), которое выглядит многообещающим, но у меня возникли проблемы с концепцией.

Короче говоря, если у меня есть абзац в основном тексте, и когда я нажимаю на слово, как мне найти ограничительную рамку для этого слова?

Ответ 1

Установите атрибут в атрибутной строке, которая не будет влиять на отображение, но заставит его выложить как отдельный глиф-прогон, а затем использовать CoreText для компоновки строки

CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString(attrString);
CTFrameRef ctframe = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, 0), path, NULL);

Теперь вам нужно будет искать рамку, чтобы найти соответствующий фрагмент текста. Получите массив CTLineRef с помощью CTFrameGetLines().

Итерации через массив, тестирование, если касание было на этой строке, путем проверки, что оно находится в пределах rect, возвращаемого CTLineGetImageBounds(). Если это так, теперь просматривайте глиф-пробеги в строке.

Снова, вы можете получить массив CTRunRef с CTLineGetGlyphRuns(). Проверьте, был ли кран включен в глиф, с CTRunGetImageBounds(), и если бы вы могли найти диапазон индексов в исходной атрибутной строке, которая соответствует значению глифа с CTRunGetStringIndices().

Ответ 2

вам нужно найти Y по CTLine и X по ширине и высоте CTRun, которые вы можете получить по слову и самому шрифту. плохой атташе моей ссылки на проект, его действительно простой код, но вы можете reedit, чтобы удовлетворить ваши потребности. надеюсь, что это поможет приветствовать, если вы улучшите общую логику, пожалуйста, дайте мне знать спасибо. textViewProject

Ответ 3

Ссылка, предоставленная Джорджем, была очень полезной и получила то, что я хотел. Но случилось странное. Он работал в iOS SDK 4.0, но в iOS SDK 5 позиция ссылки появилась в неправильном положении на представлении.

Поэтому мне пришлось немного изменить код. Для x координаты сенсорной кнопки мне пришлось использовать CTRunGetTypographicBounds вместо функции CTRunGetImageBounds.

Итак, над всем, в измененном коде: Координата y, ширина и высота вычислялись с использованием CTRunGetImageBounds. И координата x была рассчитана с использованием CTRunGetTypographicBounds.

Ответ 4

Я работаю над небольшой библиотекой, которая делает именно это. Вы можете найти его здесь: https://github.com/pothibo/CMFramework

Однако эта библиотека находится в альфа-стадии, там нужна оптимизация, и некоторые функции отсутствуют (высота строки является одной из неотложных функций, которые я хочу добавить)

Если вы решили использовать его и найти проблему, не стесняйтесь публиковать сообщения о github!