Для UILabel
я хотел бы узнать, какой индекс символа находится в определенной точке, полученной от события касания. Я хотел бы решить эту проблему для iOS 7 с помощью Text Kit.Индекс символов в точке касания для UILabel
Поскольку UILabel не предоставляет доступ к своему NSLayoutManager
, я создал свой собственный на основе UILabel
«s конфигурации, как это:
- (void)textTapped:(UITapGestureRecognizer *)recognizer
{
if (recognizer.state == UIGestureRecognizerStateEnded) {
CGPoint location = [recognizer locationInView:self];
NSTextStorage *textStorage = [[NSTextStorage alloc] initWithAttributedString:self.attributedText];
NSLayoutManager *layoutManager = [[NSLayoutManager alloc] init];
[textStorage addLayoutManager:layoutManager];
NSTextContainer *textContainer = [[NSTextContainer alloc] initWithSize:self.bounds.size];
[layoutManager addTextContainer:textContainer];
textContainer.maximumNumberOfLines = self.numberOfLines;
textContainer.lineBreakMode = self.lineBreakMode;
NSUInteger characterIndex = [layoutManager characterIndexForPoint:location
inTextContainer:textContainer
fractionOfDistanceBetweenInsertionPoints:NULL];
if (characterIndex < textStorage.length) {
NSRange range = NSMakeRange(characterIndex, 1);
NSString *value = [self.text substringWithRange:range];
NSLog(@"%@, %zd, %zd", value, range.location, range.length);
}
}
}
Код выше в UILabel
подкласса с UITapGestureRecognizer
сконфигурированной для вызова textTapped:
(Gist).
Результирующий индекс символов имеет смысл (увеличивается при нажатии слева направо), но неверен (последний символ достигнут примерно в половине ширины метки). Похоже, что размер шрифта или размер текстового контейнера не настроен должным образом, но не может найти проблему.
Я бы хотел, чтобы мой класс был подклассом UILabel
вместо UITextView
. Кто-нибудь решил эту проблему для UILabel
?
Update: я провел билет DTS на этот вопрос и инженер Apple, рекомендуется отменить UILabel
«s drawTextInRect:
с реализацией, которая использует свой собственный менеджер компоновки, похожий на этот фрагмент кода:
- (void)drawTextInRect:(CGRect)rect
{
[yourLayoutManager drawGlyphsForGlyphRange:NSMakeRange(0, yourTextStorage.length) atPoint:CGPointMake(0, 0)];
}
Я думаю, что было бы очень сложно сохранить мой собственный менеджер компоновки в синхронизации с настройками ярлыка, поэтому я, вероятно, поеду с UITextView
, несмотря на то, что я предпочитаю UILabel
.
Обновление 2: В конце концов, я решил использовать UITextView
. Цель всего этого заключалась в обнаружении ответвлений ссылок, встроенных в текст. Я попытался использовать NSLinkAttributeName
, но эта установка не вызывала обратный вызов делегата при быстром нажатии ссылки. Вместо этого вам нужно нажать ссылку на определенное время - очень раздражает. Поэтому я создал CCHLinkTextView, у которого нет этой проблемы.
Поздняя реакция; трюк для меня, чтобы заставить это работать, это строка 'textContainer.lineFragmentPadding = 0;', которая отсутствует в вашем примере, но присутствует в ответах ниже на @Alexey Ishkov и @Kai Burghardt. Мне не пришлось взломать контейнер с номером 100. – Koen