У меня есть UILabel, у которого есть текстовые и 2-месячные имена, такие как "В январе и июле солнечный блеск будет пиком" Я подклассифицировал UILabel и добавил к нему событие touch. Теперь я хочу получить слово под текстом, где пользователь коснулся и узнать, коснулся ли пользователь январь/июль или нет. Возможно ли это?
UILabel touch и получить текст, который коснулся
Ответ 1
Я думаю, вы найдете то, что ищете в документации для UITextInputProtocol.
Для получения более подробной информации посетите веб-сайт Apple "Руководство по редактированию текста, Интернета и редактирования" , в частности, в разделе "Экскурсия по UITextInput реализации". В нем обсуждается, как вы можете создавать индексированные позиции в тексте и спрашивать, касается какой позиции текста они приземлились ближе всего.
Apple ссылается на образец, спроецированный под названием SimpleTextInput
, но я не могу его найти. Я буду продолжать искать.
Ответ 2
Я применил ваш вопрос, просто для удовольствия на мой блог.
Просто я подклассифицировал UILabel
, добавив touchEnded
, чтобы распознать позицию касания и положение букв.
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [[touches allObjects] objectAtIndex:0];
CGPoint pos = [touch locationInView:self];
int sizes[self.text.length];
for ( int i=0; i<self.text.length; i++ )
{
char letter = [self.text characterAtIndex:i];
NSString *letterStr = [NSString stringWithFormat:@"%c", letter];
CGSize letterSize = [letterStr sizeWithFont:self.font];
sizes[i] = letterSize.width;
}
int sum = 0;
for ( int i=0; i<self.text.length; i++)
{
sum += sizes[i];
if ( sum >= pos.x )
{
[ _delegate didLetterFound:[ self.text characterAtIndex:i] ];
return;
}
}
}
Надеюсь, что это поможет веселит.
Ответ 3
Я справился с этой проблемой, поставив трансапарентные UIView на вершине UILabel, которые были подключены для обработки событий касания. Вы можете отрегулировать положение и размер ярлыков зоны вызова, вычислив размер соответствующих частей текста. Этот подход также имеет то преимущество, что вы можете настроить размеры зон попадания, чтобы сделать их более крупными и так легче нажимать жирными пальцами.
Ответ 4
У меня была аналогичная проблема с оригинальным плакатом. Я хотел, чтобы пользователь имел возможность долгое нажатие на UILabel, который показывал список строк, разделенных запятыми, и извлекал подстроку, соответствующую местоположению касания между ближайшими закрывающими запятыми.
Проблема в том, что UILabel не реализует протокол UITextInput, иначе реализация была бы простой.
Мне не нравились какие-либо из предложенных обходных решений, которые я нашел, поэтому я решил придумать свое решение. После некоторых размышлений и исследований я понял, что, хотя UILabel не поддерживает UITextInput, UITextView делает. Я не хотел заменять все UILabels в пользовательском интерфейсе с помощью UITextViews, поэтому я подумал: "Почему бы не программно создать UITextView за кулисами, с теми же параметрами рендеринга текста и использовать его методы UITextInput для сопоставления точки касания с нужная подстрока?".
Это оказалось идеальным решением с моей точки зрения.
Я подключил UILongPressGestureRecognizer к UILabels и вызвал следующую функцию в обработчике жестов:
-(NSString*)commaDelineatedTextAtTouchPosition:(UILongPressGestureRecognizer*)longPress
{
UILabel *gestureRecipient = (UILabel*)longPress.view;
UITextView *textRegionClone = [[UITextView alloc] initWithFrame:gestureRecipient.frame];
// tweak the text view content area to get the same rendering (placement and wrapping)
textRegionClone.textContainerInset = UIEdgeInsetsMake(0.0, -5.0, 0.0, -5.0);
// copy the label text properties
textRegionClone.text = gestureRecipient.text;
textRegionClone.font = gestureRecipient.font;
[textRegionClone setNeedsDisplay];
CGPoint loc = [longPress locationInView:gestureRecipient];
UITextPosition *charR = [textRegionClone closestPositionToPoint:loc];
id<UITextInputTokenizer> tokenizer = textRegionClone.tokenizer;
UITextRange *searchRange = [tokenizer rangeEnclosingPosition:charR withGranularity:UITextGranularityCharacter inDirection:UITextStorageDirectionBackward];
NSString *commaEnclosedText = @"";
if (searchRange != nil) {
NSString *tapChar = [textRegionClone textInRange:searchRange];
if ([tapChar isEqualToString:@","]) { // tapped right on a ","
// move the end of the range to immediately before the ","
searchRange = [textRegionClone textRangeFromPosition:searchRange.start toPosition:[textRegionClone positionFromPosition:searchRange.end offset:-1]];
}
UITextPosition *docStart = textRegionClone.beginningOfDocument;
// search back to find the leading comma or the beginning of the text
do {
searchRange = [textRegionClone textRangeFromPosition:[textRegionClone positionFromPosition:searchRange.start offset:-1] toPosition:searchRange.end];
commaEnclosedText = [textRegionClone textInRange:searchRange];
}
while (([searchRange.start isEqual:docStart] == NO) && ([commaEnclosedText characterAtIndex:0] != ','));
// now search forward to the trailing comma or the end of the text
UITextPosition *docEnd = textRegionClone.endOfDocument;
while (([searchRange.end isEqual:docEnd] == NO) && ([commaEnclosedText characterAtIndex:commaEnclosedText.length - 1] != ',')) {
searchRange = [textRegionClone textRangeFromPosition:searchRange.start toPosition:[textRegionClone positionFromPosition:searchRange.end offset:1]];
commaEnclosedText = [textRegionClone textInRange:searchRange];
}
commaEnclosedText = [[commaEnclosedText stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@","]] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
}
return commaEnclosedText;
}
Единственное, что немного взломано в этом методе - это то, что вам нужно вручную настроить рендеринг в UITextView, отредактировав область textContainerInset. В противном случае вы не получите точно такую же упаковку и размещение текста в UITextView, как в UILabel. В противном случае это достаточно общий код, который должен работать для кого-либо еще.
Ответ 5
- (void)tapped:(UITapGestureRecognizer *)tap
{
CGPoint location = [tap locationInView:_label];
NSDictionary *attribute = @{NSFontAttributeName: _label.font};
CGFloat width = 0;
for (int i = 0; i substringWithRange:NSMakeRange(i, 1)];
CGSize lettersize = [letterStr sizeWithAttributes:attribute];
width += lettersize.width;
if (width >= location.x ) {
NSLog(@"str: %@", letterStr);
break;
}
}
}