Ответ 1
Мне удалось достичь вышеупомянутого эффекта, поэтому подумал, что я отправлю ответ за то же самое.
Если у кого-то есть предложения по повышению эффективности, пожалуйста, не стесняйтесь. Я обязательно буду отмечать ваш ответ как правильный.:)
Для этого вам нужно добавить "настраиваемый атрибут" на NSAttributedString
.
В принципе, это означает, что вы можете добавить любую пару "ключ-значение", если это то, что вы можете добавить к экземпляру NSDictionary
. Если система не распознает этот атрибут, он ничего не делает. Для вас, как разработчика, вы можете предоставить настраиваемую реализацию и поведение для этого атрибута.
В целях этого ответа предположим, что я добавил пользовательский атрибут: @"MyRoundedBackgroundColor"
со значением [UIColor greenColor]
.
В следующих шагах вам нужно будет понять, как CoreText
получает материал. Ознакомьтесь с Руководством по программированию ядра Apple Core для понимания того, что работает/глиф/маркер/символ и т.д.
Итак, вот шаги:
- Создайте пользовательский подкласс UIView.
- У вас есть свойство для принятия
NSAttributedString
. - Создайте
CTFramesetter
с помощью этого экземпляраNSAttributedString
. - Переопределить метод
drawRect:
- Создайте экземпляр
CTFrame
изCTFramesetter
.- Вам нужно указать
CGPathRef
, чтобы создатьCTFrame
. Сделайте, чтобыCGPath
был таким же, как кадр, в который вы хотите нарисовать текст.
- Вам нужно указать
- Получить текущий графический контекст и перевернуть текстовую систему координат.
- Используя
CTFrameGetLines(...)
, получите все строки вCTFrame
, которые вы только что создали. - Используя
CTFrameGetLineOrigins(...)
, получите все исходные строки дляCTFrame
. - Запустите a
for loop
- для каждой строки в массивеCTLine
... - Установите текстовую позицию в начало
CTLine
с помощьюCGContextSetTextPosition(...)
. - Используя
CTLineGetGlyphRuns(...)
, выполните все действия Glyph (CTRunRef
) изCTLine
. - Запустите еще один
for loop
- для каждого glyphRun в массивеCTRun
... - Получить диапазон выполнения с помощью
CTRunGetStringRange(...)
. - Получить типографские границы с помощью
CTRunGetTypographicBounds(...)
. - Получить смещение x для выполнения с помощью
CTLineGetOffsetForStringIndex(...)
. - Вычислить ограничивающий прямоугольник (назовем его
runBounds
), используя значения, возвращаемые из вышеупомянутых функций.- Помните -
CTRunGetTypographicBounds(...)
требует указателей на переменные для хранения "восхождения" и "спуска" текста. Вам нужно добавить их, чтобы получить высоту выполнения.
- Помните -
- Получить атрибуты для запуска с помощью
CTRunGetAttributes(...)
. - Проверьте, содержит ли словарь атрибута ваш атрибут.
- Если ваш атрибут существует, вычислите границы прямоугольника, который должен быть окрашен.
- Основной текст имеет начало строки на базовой линии. Нам нужно извлечь из нижней точки текста верхнюю точку. Таким образом, нам нужно настроить для снижения.
- Итак, вычтите спуск из ограничивающего прямоугольника, который мы вычислили на этапе 16 (
runBounds
). - Теперь, когда у нас есть
runBounds
, мы знаем, в какой области мы хотим рисовать - теперь мы можем использовать любой из методовCoreGraphis
/UIBezierPath
для рисования и заполнения прямоугольника с помощью определенных закругленных углов.-
UIBezierPath
имеет метод класса удобства, называемыйbezierPathWithRoundedRect:byRoundingCorners:cornerRadii:
, который позволяет вам обходить определенные углы. Вы указываете углы с использованием бит-масок во втором параметре.
-
- Теперь, когда вы заполнили прямоугольник, просто нарисуйте глиф-прогон с помощью
CTRunDraw(...)
. - Празднуйте победу за то, что создали свой собственный атрибут - пить пиво или что-то в этом роде!: D
Относительно обнаружения того, что диапазон атрибутов распространяется на несколько прогонов, вы можете получить весь эффективный диапазон вашего настраиваемого атрибута, когда первый запуск встречает этот атрибут. Если вы обнаружите, что длина максимального эффективного диапазона вашего атрибута больше, чем длина вашего прогона, вам нужно нарисовать острые углы с правой стороны (слева направо script). Более математика позволит вам определить стиль подсветки для следующей строки.:)
Прилагается скриншот эффекта. Ящик сверху - это стандартный UITextView
, для которого я установил атрибутText. Ящик внизу - тот, который был реализован с использованием вышеуказанных шагов. Такая же атрибутная строка была установлена как для текстовых.
Опять же, если есть лучший подход, чем тот, который я использовал, пожалуйста, дайте мне знать!: D
Надеюсь, это поможет сообществу.:)
Ура!