2014-08-27 3 views
3

Я пытаюсь добавить точечный стиль подчеркивания в NSAttributedString (на iOS7 +/TextKit). Конечно, я попробовал встроенный NSUnderlinePatternDot:Настроить шаблон подчеркивания в NSAttributedString (iOS7 +)

NSString *string = self.label.text; 
NSRange underlineRange = [string rangeOfString:@"consetetur sadipscing elitr"]; 

NSMutableAttributedString *attString = [[NSMutableAttributedString alloc] initWithString:string]; 
[attString addAttributes:@{NSUnderlineStyleAttributeName: @(NSUnderlineStyleSingle | NSUnderlinePatternDot)} range:underlineRange]; 

self.label.attributedText = attString; 

Однако стиль производства это на самом деле, а пунктирная чем пунктир:

screenshot

Я пропускаю что-то очевидное здесь (NSUnderlinePatternReallyDotted? ;)) или есть ли способ настроить шаблон-точка?

ответ

0

Я знаю, что это двухлетняя история, но, возможно, это поможет кому-то, сталкивающемуся с той же проблемой, как и на прошлой неделе. Мое обходное решение заключалось в подклассе UITextView, добавлении subview (контейнер с пунктирными линиями) и использовании метода layoutManager textView enumerateLineFragmentsForGlyphRange для получения количества строк и их кадров. Зная рамку линии, я вычислил y, где мне нужны точки. Таким образом, я создал представление (lineView, в котором я нарисовал точки), установил clipsToBounds в YES, ширину, равную ширине textView, а затем , добавленную в качестве подсмотра в линияхContainer при этом y. После этого я установил линии lineView, который был возвращен enumerateLineFragmentsForGlyphRange. Для нескольких строк такой же подход: обновить кадры, добавить новые строки или удалить в соответствии с тем, что возвращает enumerateLineFragmentsForGlyphRange. Этот метод вызывается в textViewDidChange после каждого обновления текста. Вот код, чтобы получить массив строк и их кадров

NSLayoutManager *layoutManager = [self layoutManager]; 
[layoutManager enumerateLineFragmentsForGlyphRange:NSMakeRange(0, [layoutManager numberOfGlyphs]) 
             usingBlock:^(CGRect rect, CGRect usedRect, NSTextContainer *textContainer, NSRange glyphRange, BOOL *stop) { 
                 [linesFramesArray addObject:NSStringFromCGRect(usedRect)]; 
                } 
]; 
1

Я потратил немного времени, играя с Text Kit, чтобы получить это и другие подобные сценарии работы. Фактическое решение Text Kit для этой задачи подкласс NSLayoutManager и переопределить drawUnderline(forGlyphRange:underlineType:baselineOffset:lineFragmentRect:lineFragmentGlyphRange:containerOrigin:)

Это метод, который вызывается на самом деле сделать подчеркивание, что запрошенные атрибуты в NSTextStorage.Вот описание параметров, которые получают передается в:

  • glyphRange индекс первого символа и число следующих глифы быть подчеркнуты
  • underlineTypeNSUnderlineStyle значение атрибута NSUnderlineAttributeName
  • baselineOffset расстояние между нижней границей рамки и смещением базовой линии для глифов в указанном диапазоне
  • lineFragmentRect прямоугольник, который охватывает всю строку, которая содержит glyphRange
  • lineFragmentGlyphRange желаемый диапазон глиф, который составляет всю строку, которая содержит glyphRange
  • containerOrigin смещение контейнера в пределах текст, к которому относится

Шаги, чтобы сделать подчеркивание:

  1. Найдите NSTextContainer, который содержит glyphRange с использованием NSLayoutManager.textContainer(forGlyphAt:effectiveRange:).
  2. Получить ограничивающий прямоугольник для glyphRange с помощью NSLayoutManager.boundingRect(forGlyphRange:in:)
  3. Смещения ограничивающего прямоугольника в тексте контейнер происхождения с использованием CGRect.offsetBy(dx:dy:)
  4. Нарисуйте ваш заказ подчеркнуть то между нижней частью смещения ограничивающего прямоугольника и базовой линией (как определен baselineOffset)